##// END OF EJS Templates
Fixed workflow rules when user has duplicated role by inheritance (#19569)....
Jean-Philippe Lang -
r13797:a9f052532e3e
parent child
Show More
@@ -1,139 +1,139
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Member < ActiveRecord::Base
18 class Member < ActiveRecord::Base
19 belongs_to :user
19 belongs_to :user
20 belongs_to :principal, :foreign_key => 'user_id'
20 belongs_to :principal, :foreign_key => 'user_id'
21 has_many :member_roles, :dependent => :destroy
21 has_many :member_roles, :dependent => :destroy
22 has_many :roles, :through => :member_roles
22 has_many :roles, lambda {uniq}, :through => :member_roles
23 belongs_to :project
23 belongs_to :project
24
24
25 validates_presence_of :principal, :project
25 validates_presence_of :principal, :project
26 validates_uniqueness_of :user_id, :scope => :project_id
26 validates_uniqueness_of :user_id, :scope => :project_id
27 validate :validate_role
27 validate :validate_role
28 attr_protected :id
28 attr_protected :id
29
29
30 before_destroy :set_issue_category_nil
30 before_destroy :set_issue_category_nil
31
31
32 def role
32 def role
33 end
33 end
34
34
35 def role=
35 def role=
36 end
36 end
37
37
38 def name
38 def name
39 self.user.name
39 self.user.name
40 end
40 end
41
41
42 alias :base_role_ids= :role_ids=
42 alias :base_role_ids= :role_ids=
43 def role_ids=(arg)
43 def role_ids=(arg)
44 ids = (arg || []).collect(&:to_i) - [0]
44 ids = (arg || []).collect(&:to_i) - [0]
45 # Keep inherited roles
45 # Keep inherited roles
46 ids += member_roles.select {|mr| !mr.inherited_from.nil?}.collect(&:role_id)
46 ids += member_roles.select {|mr| !mr.inherited_from.nil?}.collect(&:role_id)
47
47
48 new_role_ids = ids - role_ids
48 new_role_ids = ids - role_ids
49 # Add new roles
49 # Add new roles
50 new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id, :member => self) }
50 new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id, :member => self) }
51 # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
51 # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
52 member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
52 member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
53 if member_roles_to_destroy.any?
53 if member_roles_to_destroy.any?
54 member_roles_to_destroy.each(&:destroy)
54 member_roles_to_destroy.each(&:destroy)
55 end
55 end
56 end
56 end
57
57
58 def <=>(member)
58 def <=>(member)
59 a, b = roles.sort.first, member.roles.sort.first
59 a, b = roles.sort.first, member.roles.sort.first
60 if a == b
60 if a == b
61 if principal
61 if principal
62 principal <=> member.principal
62 principal <=> member.principal
63 else
63 else
64 1
64 1
65 end
65 end
66 elsif a
66 elsif a
67 a <=> b
67 a <=> b
68 else
68 else
69 1
69 1
70 end
70 end
71 end
71 end
72
72
73 def deletable?
73 def deletable?
74 member_roles.detect {|mr| mr.inherited_from}.nil?
74 member_roles.detect {|mr| mr.inherited_from}.nil?
75 end
75 end
76
76
77 def destroy
77 def destroy
78 if member_roles.reload.present?
78 if member_roles.reload.present?
79 # destroying the last role will destroy another instance
79 # destroying the last role will destroy another instance
80 # of the same Member record, #super would then trigger callbacks twice
80 # of the same Member record, #super would then trigger callbacks twice
81 member_roles.destroy_all
81 member_roles.destroy_all
82 @destroyed = true
82 @destroyed = true
83 freeze
83 freeze
84 else
84 else
85 super
85 super
86 end
86 end
87 end
87 end
88
88
89 def include?(user)
89 def include?(user)
90 if principal.is_a?(Group)
90 if principal.is_a?(Group)
91 !user.nil? && user.groups.include?(principal)
91 !user.nil? && user.groups.include?(principal)
92 else
92 else
93 self.user == user
93 self.user == user
94 end
94 end
95 end
95 end
96
96
97 def set_issue_category_nil
97 def set_issue_category_nil
98 if user_id && project_id
98 if user_id && project_id
99 # remove category based auto assignments for this member
99 # remove category based auto assignments for this member
100 IssueCategory.where(["project_id = ? AND assigned_to_id = ?", project_id, user_id]).
100 IssueCategory.where(["project_id = ? AND assigned_to_id = ?", project_id, user_id]).
101 update_all("assigned_to_id = NULL")
101 update_all("assigned_to_id = NULL")
102 end
102 end
103 end
103 end
104
104
105 # Creates memberships for principal with the attributes
105 # Creates memberships for principal with the attributes
106 # * project_ids : one or more project ids
106 # * project_ids : one or more project ids
107 # * role_ids : ids of the roles to give to each membership
107 # * role_ids : ids of the roles to give to each membership
108 #
108 #
109 # Example:
109 # Example:
110 # Member.create_principal_memberships(user, :project_ids => [2, 5], :role_ids => [1, 3]
110 # Member.create_principal_memberships(user, :project_ids => [2, 5], :role_ids => [1, 3]
111 def self.create_principal_memberships(principal, attributes)
111 def self.create_principal_memberships(principal, attributes)
112 members = []
112 members = []
113 if attributes
113 if attributes
114 project_ids = Array.wrap(attributes[:project_ids] || attributes[:project_id])
114 project_ids = Array.wrap(attributes[:project_ids] || attributes[:project_id])
115 role_ids = attributes[:role_ids]
115 role_ids = attributes[:role_ids]
116 project_ids.each do |project_id|
116 project_ids.each do |project_id|
117 members << Member.new(:principal => principal, :role_ids => role_ids, :project_id => project_id)
117 members << Member.new(:principal => principal, :role_ids => role_ids, :project_id => project_id)
118 end
118 end
119 principal.members << members
119 principal.members << members
120 end
120 end
121 members
121 members
122 end
122 end
123
123
124 # Finds or initilizes a Member for the given project and principal
124 # Finds or initilizes a Member for the given project and principal
125 def self.find_or_new(project, principal)
125 def self.find_or_new(project, principal)
126 project_id = project.is_a?(Project) ? project.id : project
126 project_id = project.is_a?(Project) ? project.id : project
127 principal_id = principal.is_a?(Principal) ? principal.id : principal
127 principal_id = principal.is_a?(Principal) ? principal.id : principal
128
128
129 member = Member.find_by_project_id_and_user_id(project_id, principal_id)
129 member = Member.find_by_project_id_and_user_id(project_id, principal_id)
130 member ||= Member.new(:project_id => project_id, :user_id => principal_id)
130 member ||= Member.new(:project_id => project_id, :user_id => principal_id)
131 member
131 member
132 end
132 end
133
133
134 protected
134 protected
135
135
136 def validate_role
136 def validate_role
137 errors.add_on_empty :role if member_roles.empty? && roles.empty?
137 errors.add_on_empty :role if member_roles.empty? && roles.empty?
138 end
138 end
139 end
139 end
@@ -1,2642 +1,2663
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class IssueTest < ActiveSupport::TestCase
20 class IssueTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles,
21 fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles,
22 :groups_users,
22 :groups_users,
23 :trackers, :projects_trackers,
23 :trackers, :projects_trackers,
24 :enabled_modules,
24 :enabled_modules,
25 :versions,
25 :versions,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
27 :enumerations,
27 :enumerations,
28 :issues, :journals, :journal_details,
28 :issues, :journals, :journal_details,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
30 :time_entries
30 :time_entries
31
31
32 include Redmine::I18n
32 include Redmine::I18n
33
33
34 def setup
34 def setup
35 set_language_if_valid 'en'
35 set_language_if_valid 'en'
36 end
36 end
37
37
38 def teardown
38 def teardown
39 User.current = nil
39 User.current = nil
40 end
40 end
41
41
42 def test_initialize
42 def test_initialize
43 issue = Issue.new
43 issue = Issue.new
44
44
45 assert_nil issue.project_id
45 assert_nil issue.project_id
46 assert_nil issue.tracker_id
46 assert_nil issue.tracker_id
47 assert_nil issue.status_id
47 assert_nil issue.status_id
48 assert_nil issue.author_id
48 assert_nil issue.author_id
49 assert_nil issue.assigned_to_id
49 assert_nil issue.assigned_to_id
50 assert_nil issue.category_id
50 assert_nil issue.category_id
51
51
52 assert_equal IssuePriority.default, issue.priority
52 assert_equal IssuePriority.default, issue.priority
53 end
53 end
54
54
55 def test_create
55 def test_create
56 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
56 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
57 :status_id => 1, :priority => IssuePriority.all.first,
57 :status_id => 1, :priority => IssuePriority.all.first,
58 :subject => 'test_create',
58 :subject => 'test_create',
59 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
59 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
60 assert issue.save
60 assert issue.save
61 issue.reload
61 issue.reload
62 assert_equal 1.5, issue.estimated_hours
62 assert_equal 1.5, issue.estimated_hours
63 end
63 end
64
64
65 def test_create_minimal
65 def test_create_minimal
66 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create')
66 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create')
67 assert issue.save
67 assert issue.save
68 assert_equal issue.tracker.default_status, issue.status
68 assert_equal issue.tracker.default_status, issue.status
69 assert issue.description.nil?
69 assert issue.description.nil?
70 assert_nil issue.estimated_hours
70 assert_nil issue.estimated_hours
71 end
71 end
72
72
73 def test_start_date_format_should_be_validated
73 def test_start_date_format_should_be_validated
74 set_language_if_valid 'en'
74 set_language_if_valid 'en'
75 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
75 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
76 issue = Issue.new(:start_date => invalid_date)
76 issue = Issue.new(:start_date => invalid_date)
77 assert !issue.valid?
77 assert !issue.valid?
78 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
78 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
79 end
79 end
80 end
80 end
81
81
82 def test_due_date_format_should_be_validated
82 def test_due_date_format_should_be_validated
83 set_language_if_valid 'en'
83 set_language_if_valid 'en'
84 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
84 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
85 issue = Issue.new(:due_date => invalid_date)
85 issue = Issue.new(:due_date => invalid_date)
86 assert !issue.valid?
86 assert !issue.valid?
87 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
87 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
88 end
88 end
89 end
89 end
90
90
91 def test_due_date_lesser_than_start_date_should_not_validate
91 def test_due_date_lesser_than_start_date_should_not_validate
92 set_language_if_valid 'en'
92 set_language_if_valid 'en'
93 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
93 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
94 assert !issue.valid?
94 assert !issue.valid?
95 assert_include 'Due date must be greater than start date', issue.errors.full_messages
95 assert_include 'Due date must be greater than start date', issue.errors.full_messages
96 end
96 end
97
97
98 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
98 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
99 issue = Issue.generate(:start_date => '2013-06-04')
99 issue = Issue.generate(:start_date => '2013-06-04')
100 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
100 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
101 assert !issue.valid?
101 assert !issue.valid?
102 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
102 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
103 end
103 end
104
104
105 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
105 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
106 issue = Issue.generate!(:start_date => '2013-06-04')
106 issue = Issue.generate!(:start_date => '2013-06-04')
107 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
107 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
108 issue.start_date = '2013-06-07'
108 issue.start_date = '2013-06-07'
109 assert !issue.valid?
109 assert !issue.valid?
110 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
110 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
111 end
111 end
112
112
113 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
113 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
114 issue = Issue.generate!(:start_date => '2013-06-04')
114 issue = Issue.generate!(:start_date => '2013-06-04')
115 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
115 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
116 assert issue.valid?
116 assert issue.valid?
117 end
117 end
118
118
119 def test_estimated_hours_should_be_validated
119 def test_estimated_hours_should_be_validated
120 set_language_if_valid 'en'
120 set_language_if_valid 'en'
121 ['-2'].each do |invalid|
121 ['-2'].each do |invalid|
122 issue = Issue.new(:estimated_hours => invalid)
122 issue = Issue.new(:estimated_hours => invalid)
123 assert !issue.valid?
123 assert !issue.valid?
124 assert_include 'Estimated time is invalid', issue.errors.full_messages
124 assert_include 'Estimated time is invalid', issue.errors.full_messages
125 end
125 end
126 end
126 end
127
127
128 def test_create_with_required_custom_field
128 def test_create_with_required_custom_field
129 set_language_if_valid 'en'
129 set_language_if_valid 'en'
130 field = IssueCustomField.find_by_name('Database')
130 field = IssueCustomField.find_by_name('Database')
131 field.update_attribute(:is_required, true)
131 field.update_attribute(:is_required, true)
132
132
133 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
133 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
134 :status_id => 1, :subject => 'test_create',
134 :status_id => 1, :subject => 'test_create',
135 :description => 'IssueTest#test_create_with_required_custom_field')
135 :description => 'IssueTest#test_create_with_required_custom_field')
136 assert issue.available_custom_fields.include?(field)
136 assert issue.available_custom_fields.include?(field)
137 # No value for the custom field
137 # No value for the custom field
138 assert !issue.save
138 assert !issue.save
139 assert_equal ["Database cannot be blank"], issue.errors.full_messages
139 assert_equal ["Database cannot be blank"], issue.errors.full_messages
140 # Blank value
140 # Blank value
141 issue.custom_field_values = { field.id => '' }
141 issue.custom_field_values = { field.id => '' }
142 assert !issue.save
142 assert !issue.save
143 assert_equal ["Database cannot be blank"], issue.errors.full_messages
143 assert_equal ["Database cannot be blank"], issue.errors.full_messages
144 # Invalid value
144 # Invalid value
145 issue.custom_field_values = { field.id => 'SQLServer' }
145 issue.custom_field_values = { field.id => 'SQLServer' }
146 assert !issue.save
146 assert !issue.save
147 assert_equal ["Database is not included in the list"], issue.errors.full_messages
147 assert_equal ["Database is not included in the list"], issue.errors.full_messages
148 # Valid value
148 # Valid value
149 issue.custom_field_values = { field.id => 'PostgreSQL' }
149 issue.custom_field_values = { field.id => 'PostgreSQL' }
150 assert issue.save
150 assert issue.save
151 issue.reload
151 issue.reload
152 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
152 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
153 end
153 end
154
154
155 def test_create_with_group_assignment
155 def test_create_with_group_assignment
156 with_settings :issue_group_assignment => '1' do
156 with_settings :issue_group_assignment => '1' do
157 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
157 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
158 :subject => 'Group assignment',
158 :subject => 'Group assignment',
159 :assigned_to_id => 11).save
159 :assigned_to_id => 11).save
160 issue = Issue.order('id DESC').first
160 issue = Issue.order('id DESC').first
161 assert_kind_of Group, issue.assigned_to
161 assert_kind_of Group, issue.assigned_to
162 assert_equal Group.find(11), issue.assigned_to
162 assert_equal Group.find(11), issue.assigned_to
163 end
163 end
164 end
164 end
165
165
166 def test_create_with_parent_issue_id
166 def test_create_with_parent_issue_id
167 issue = Issue.new(:project_id => 1, :tracker_id => 1,
167 issue = Issue.new(:project_id => 1, :tracker_id => 1,
168 :author_id => 1, :subject => 'Group assignment',
168 :author_id => 1, :subject => 'Group assignment',
169 :parent_issue_id => 1)
169 :parent_issue_id => 1)
170 assert_save issue
170 assert_save issue
171 assert_equal 1, issue.parent_issue_id
171 assert_equal 1, issue.parent_issue_id
172 assert_equal Issue.find(1), issue.parent
172 assert_equal Issue.find(1), issue.parent
173 end
173 end
174
174
175 def test_create_with_sharp_parent_issue_id
175 def test_create_with_sharp_parent_issue_id
176 issue = Issue.new(:project_id => 1, :tracker_id => 1,
176 issue = Issue.new(:project_id => 1, :tracker_id => 1,
177 :author_id => 1, :subject => 'Group assignment',
177 :author_id => 1, :subject => 'Group assignment',
178 :parent_issue_id => "#1")
178 :parent_issue_id => "#1")
179 assert_save issue
179 assert_save issue
180 assert_equal 1, issue.parent_issue_id
180 assert_equal 1, issue.parent_issue_id
181 assert_equal Issue.find(1), issue.parent
181 assert_equal Issue.find(1), issue.parent
182 end
182 end
183
183
184 def test_create_with_invalid_parent_issue_id
184 def test_create_with_invalid_parent_issue_id
185 set_language_if_valid 'en'
185 set_language_if_valid 'en'
186 issue = Issue.new(:project_id => 1, :tracker_id => 1,
186 issue = Issue.new(:project_id => 1, :tracker_id => 1,
187 :author_id => 1, :subject => 'Group assignment',
187 :author_id => 1, :subject => 'Group assignment',
188 :parent_issue_id => '01ABC')
188 :parent_issue_id => '01ABC')
189 assert !issue.save
189 assert !issue.save
190 assert_equal '01ABC', issue.parent_issue_id
190 assert_equal '01ABC', issue.parent_issue_id
191 assert_include 'Parent task is invalid', issue.errors.full_messages
191 assert_include 'Parent task is invalid', issue.errors.full_messages
192 end
192 end
193
193
194 def test_create_with_invalid_sharp_parent_issue_id
194 def test_create_with_invalid_sharp_parent_issue_id
195 set_language_if_valid 'en'
195 set_language_if_valid 'en'
196 issue = Issue.new(:project_id => 1, :tracker_id => 1,
196 issue = Issue.new(:project_id => 1, :tracker_id => 1,
197 :author_id => 1, :subject => 'Group assignment',
197 :author_id => 1, :subject => 'Group assignment',
198 :parent_issue_id => '#01ABC')
198 :parent_issue_id => '#01ABC')
199 assert !issue.save
199 assert !issue.save
200 assert_equal '#01ABC', issue.parent_issue_id
200 assert_equal '#01ABC', issue.parent_issue_id
201 assert_include 'Parent task is invalid', issue.errors.full_messages
201 assert_include 'Parent task is invalid', issue.errors.full_messages
202 end
202 end
203
203
204 def assert_visibility_match(user, issues)
204 def assert_visibility_match(user, issues)
205 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
205 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
206 end
206 end
207
207
208 def test_visible_scope_for_anonymous
208 def test_visible_scope_for_anonymous
209 # Anonymous user should see issues of public projects only
209 # Anonymous user should see issues of public projects only
210 issues = Issue.visible(User.anonymous).to_a
210 issues = Issue.visible(User.anonymous).to_a
211 assert issues.any?
211 assert issues.any?
212 assert_nil issues.detect {|issue| !issue.project.is_public?}
212 assert_nil issues.detect {|issue| !issue.project.is_public?}
213 assert_nil issues.detect {|issue| issue.is_private?}
213 assert_nil issues.detect {|issue| issue.is_private?}
214 assert_visibility_match User.anonymous, issues
214 assert_visibility_match User.anonymous, issues
215 end
215 end
216
216
217 def test_visible_scope_for_anonymous_without_view_issues_permissions
217 def test_visible_scope_for_anonymous_without_view_issues_permissions
218 # Anonymous user should not see issues without permission
218 # Anonymous user should not see issues without permission
219 Role.anonymous.remove_permission!(:view_issues)
219 Role.anonymous.remove_permission!(:view_issues)
220 issues = Issue.visible(User.anonymous).to_a
220 issues = Issue.visible(User.anonymous).to_a
221 assert issues.empty?
221 assert issues.empty?
222 assert_visibility_match User.anonymous, issues
222 assert_visibility_match User.anonymous, issues
223 end
223 end
224
224
225 def test_visible_scope_for_anonymous_without_view_issues_permissions_and_membership
225 def test_visible_scope_for_anonymous_without_view_issues_permissions_and_membership
226 Role.anonymous.remove_permission!(:view_issues)
226 Role.anonymous.remove_permission!(:view_issues)
227 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [2])
227 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [2])
228
228
229 issues = Issue.visible(User.anonymous).all
229 issues = Issue.visible(User.anonymous).all
230 assert issues.any?
230 assert issues.any?
231 assert_equal [1], issues.map(&:project_id).uniq.sort
231 assert_equal [1], issues.map(&:project_id).uniq.sort
232 assert_visibility_match User.anonymous, issues
232 assert_visibility_match User.anonymous, issues
233 end
233 end
234
234
235 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
235 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
236 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
236 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
237 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
237 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
238 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
238 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
239 assert !issue.visible?(User.anonymous)
239 assert !issue.visible?(User.anonymous)
240 end
240 end
241
241
242 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
242 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
243 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
243 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
244 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
244 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
245 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
245 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
246 assert !issue.visible?(User.anonymous)
246 assert !issue.visible?(User.anonymous)
247 end
247 end
248
248
249 def test_visible_scope_for_non_member
249 def test_visible_scope_for_non_member
250 user = User.find(9)
250 user = User.find(9)
251 assert user.projects.empty?
251 assert user.projects.empty?
252 # Non member user should see issues of public projects only
252 # Non member user should see issues of public projects only
253 issues = Issue.visible(user).to_a
253 issues = Issue.visible(user).to_a
254 assert issues.any?
254 assert issues.any?
255 assert_nil issues.detect {|issue| !issue.project.is_public?}
255 assert_nil issues.detect {|issue| !issue.project.is_public?}
256 assert_nil issues.detect {|issue| issue.is_private?}
256 assert_nil issues.detect {|issue| issue.is_private?}
257 assert_visibility_match user, issues
257 assert_visibility_match user, issues
258 end
258 end
259
259
260 def test_visible_scope_for_non_member_with_own_issues_visibility
260 def test_visible_scope_for_non_member_with_own_issues_visibility
261 Role.non_member.update_attribute :issues_visibility, 'own'
261 Role.non_member.update_attribute :issues_visibility, 'own'
262 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
262 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
263 user = User.find(9)
263 user = User.find(9)
264
264
265 issues = Issue.visible(user).to_a
265 issues = Issue.visible(user).to_a
266 assert issues.any?
266 assert issues.any?
267 assert_nil issues.detect {|issue| issue.author != user}
267 assert_nil issues.detect {|issue| issue.author != user}
268 assert_visibility_match user, issues
268 assert_visibility_match user, issues
269 end
269 end
270
270
271 def test_visible_scope_for_non_member_without_view_issues_permissions
271 def test_visible_scope_for_non_member_without_view_issues_permissions
272 # Non member user should not see issues without permission
272 # Non member user should not see issues without permission
273 Role.non_member.remove_permission!(:view_issues)
273 Role.non_member.remove_permission!(:view_issues)
274 user = User.find(9)
274 user = User.find(9)
275 assert user.projects.empty?
275 assert user.projects.empty?
276 issues = Issue.visible(user).to_a
276 issues = Issue.visible(user).to_a
277 assert issues.empty?
277 assert issues.empty?
278 assert_visibility_match user, issues
278 assert_visibility_match user, issues
279 end
279 end
280
280
281 def test_visible_scope_for_non_member_without_view_issues_permissions_and_membership
281 def test_visible_scope_for_non_member_without_view_issues_permissions_and_membership
282 Role.non_member.remove_permission!(:view_issues)
282 Role.non_member.remove_permission!(:view_issues)
283 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [2])
283 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [2])
284 user = User.find(9)
284 user = User.find(9)
285
285
286 issues = Issue.visible(user).all
286 issues = Issue.visible(user).all
287 assert issues.any?
287 assert issues.any?
288 assert_equal [1], issues.map(&:project_id).uniq.sort
288 assert_equal [1], issues.map(&:project_id).uniq.sort
289 assert_visibility_match user, issues
289 assert_visibility_match user, issues
290 end
290 end
291
291
292 def test_visible_scope_for_member
292 def test_visible_scope_for_member
293 user = User.find(9)
293 user = User.find(9)
294 # User should see issues of projects for which user has view_issues permissions only
294 # User should see issues of projects for which user has view_issues permissions only
295 Role.non_member.remove_permission!(:view_issues)
295 Role.non_member.remove_permission!(:view_issues)
296 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
296 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
297 issues = Issue.visible(user).to_a
297 issues = Issue.visible(user).to_a
298 assert issues.any?
298 assert issues.any?
299 assert_nil issues.detect {|issue| issue.project_id != 3}
299 assert_nil issues.detect {|issue| issue.project_id != 3}
300 assert_nil issues.detect {|issue| issue.is_private?}
300 assert_nil issues.detect {|issue| issue.is_private?}
301 assert_visibility_match user, issues
301 assert_visibility_match user, issues
302 end
302 end
303
303
304 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
304 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
305 user = User.find(8)
305 user = User.find(8)
306 assert user.groups.any?
306 assert user.groups.any?
307 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
307 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
308 Role.non_member.remove_permission!(:view_issues)
308 Role.non_member.remove_permission!(:view_issues)
309
309
310 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3,
310 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3,
311 :status_id => 1, :priority => IssuePriority.all.first,
311 :status_id => 1, :priority => IssuePriority.all.first,
312 :subject => 'Assignment test',
312 :subject => 'Assignment test',
313 :assigned_to => user.groups.first,
313 :assigned_to => user.groups.first,
314 :is_private => true)
314 :is_private => true)
315
315
316 Role.find(2).update_attribute :issues_visibility, 'default'
316 Role.find(2).update_attribute :issues_visibility, 'default'
317 issues = Issue.visible(User.find(8)).to_a
317 issues = Issue.visible(User.find(8)).to_a
318 assert issues.any?
318 assert issues.any?
319 assert issues.include?(issue)
319 assert issues.include?(issue)
320
320
321 Role.find(2).update_attribute :issues_visibility, 'own'
321 Role.find(2).update_attribute :issues_visibility, 'own'
322 issues = Issue.visible(User.find(8)).to_a
322 issues = Issue.visible(User.find(8)).to_a
323 assert issues.any?
323 assert issues.any?
324 assert_include issue, issues
324 assert_include issue, issues
325 end
325 end
326
326
327 def test_visible_scope_for_admin
327 def test_visible_scope_for_admin
328 user = User.find(1)
328 user = User.find(1)
329 user.members.each(&:destroy)
329 user.members.each(&:destroy)
330 assert user.projects.empty?
330 assert user.projects.empty?
331 issues = Issue.visible(user).to_a
331 issues = Issue.visible(user).to_a
332 assert issues.any?
332 assert issues.any?
333 # Admin should see issues on private projects that admin does not belong to
333 # Admin should see issues on private projects that admin does not belong to
334 assert issues.detect {|issue| !issue.project.is_public?}
334 assert issues.detect {|issue| !issue.project.is_public?}
335 # Admin should see private issues of other users
335 # Admin should see private issues of other users
336 assert issues.detect {|issue| issue.is_private? && issue.author != user}
336 assert issues.detect {|issue| issue.is_private? && issue.author != user}
337 assert_visibility_match user, issues
337 assert_visibility_match user, issues
338 end
338 end
339
339
340 def test_visible_scope_with_project
340 def test_visible_scope_with_project
341 project = Project.find(1)
341 project = Project.find(1)
342 issues = Issue.visible(User.find(2), :project => project).to_a
342 issues = Issue.visible(User.find(2), :project => project).to_a
343 projects = issues.collect(&:project).uniq
343 projects = issues.collect(&:project).uniq
344 assert_equal 1, projects.size
344 assert_equal 1, projects.size
345 assert_equal project, projects.first
345 assert_equal project, projects.first
346 end
346 end
347
347
348 def test_visible_scope_with_project_and_subprojects
348 def test_visible_scope_with_project_and_subprojects
349 project = Project.find(1)
349 project = Project.find(1)
350 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a
350 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a
351 projects = issues.collect(&:project).uniq
351 projects = issues.collect(&:project).uniq
352 assert projects.size > 1
352 assert projects.size > 1
353 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
353 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
354 end
354 end
355
355
356 def test_visible_and_nested_set_scopes
356 def test_visible_and_nested_set_scopes
357 user = User.generate!
357 user = User.generate!
358 parent = Issue.generate!(:assigned_to => user)
358 parent = Issue.generate!(:assigned_to => user)
359 assert parent.visible?(user)
359 assert parent.visible?(user)
360 child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
360 child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
361 child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
361 child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
362 parent.reload
362 parent.reload
363 child1.reload
363 child1.reload
364 child2.reload
364 child2.reload
365 assert child1.visible?(user)
365 assert child1.visible?(user)
366 assert child2.visible?(user)
366 assert child2.visible?(user)
367 assert_equal 2, parent.descendants.count
367 assert_equal 2, parent.descendants.count
368 assert_equal 2, parent.descendants.visible(user).count
368 assert_equal 2, parent.descendants.visible(user).count
369 # awesome_nested_set 2-1-stable branch has regression.
369 # awesome_nested_set 2-1-stable branch has regression.
370 # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6
370 # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6
371 # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft:
371 # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft:
372 assert_equal 2, parent.descendants.collect{|i| i}.size
372 assert_equal 2, parent.descendants.collect{|i| i}.size
373 assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size
373 assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size
374 end
374 end
375
375
376 def test_visible_scope_with_unsaved_user_should_not_raise_an_error
376 def test_visible_scope_with_unsaved_user_should_not_raise_an_error
377 user = User.new
377 user = User.new
378 assert_nothing_raised do
378 assert_nothing_raised do
379 Issue.visible(user).to_a
379 Issue.visible(user).to_a
380 end
380 end
381 end
381 end
382
382
383 def test_open_scope
383 def test_open_scope
384 issues = Issue.open.to_a
384 issues = Issue.open.to_a
385 assert_nil issues.detect(&:closed?)
385 assert_nil issues.detect(&:closed?)
386 end
386 end
387
387
388 def test_open_scope_with_arg
388 def test_open_scope_with_arg
389 issues = Issue.open(false).to_a
389 issues = Issue.open(false).to_a
390 assert_equal issues, issues.select(&:closed?)
390 assert_equal issues, issues.select(&:closed?)
391 end
391 end
392
392
393 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
393 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
394 version = Version.find(2)
394 version = Version.find(2)
395 assert version.fixed_issues.any?
395 assert version.fixed_issues.any?
396 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
396 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
397 end
397 end
398
398
399 def test_fixed_version_scope_with_empty_array_should_return_no_result
399 def test_fixed_version_scope_with_empty_array_should_return_no_result
400 assert_equal 0, Issue.fixed_version([]).count
400 assert_equal 0, Issue.fixed_version([]).count
401 end
401 end
402
402
403 def test_errors_full_messages_should_include_custom_fields_errors
403 def test_errors_full_messages_should_include_custom_fields_errors
404 field = IssueCustomField.find_by_name('Database')
404 field = IssueCustomField.find_by_name('Database')
405
405
406 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
406 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
407 :status_id => 1, :subject => 'test_create',
407 :status_id => 1, :subject => 'test_create',
408 :description => 'IssueTest#test_create_with_required_custom_field')
408 :description => 'IssueTest#test_create_with_required_custom_field')
409 assert issue.available_custom_fields.include?(field)
409 assert issue.available_custom_fields.include?(field)
410 # Invalid value
410 # Invalid value
411 issue.custom_field_values = { field.id => 'SQLServer' }
411 issue.custom_field_values = { field.id => 'SQLServer' }
412
412
413 assert !issue.valid?
413 assert !issue.valid?
414 assert_equal 1, issue.errors.full_messages.size
414 assert_equal 1, issue.errors.full_messages.size
415 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
415 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
416 issue.errors.full_messages.first
416 issue.errors.full_messages.first
417 end
417 end
418
418
419 def test_update_issue_with_required_custom_field
419 def test_update_issue_with_required_custom_field
420 field = IssueCustomField.find_by_name('Database')
420 field = IssueCustomField.find_by_name('Database')
421 field.update_attribute(:is_required, true)
421 field.update_attribute(:is_required, true)
422
422
423 issue = Issue.find(1)
423 issue = Issue.find(1)
424 assert_nil issue.custom_value_for(field)
424 assert_nil issue.custom_value_for(field)
425 assert issue.available_custom_fields.include?(field)
425 assert issue.available_custom_fields.include?(field)
426 # No change to custom values, issue can be saved
426 # No change to custom values, issue can be saved
427 assert issue.save
427 assert issue.save
428 # Blank value
428 # Blank value
429 issue.custom_field_values = { field.id => '' }
429 issue.custom_field_values = { field.id => '' }
430 assert !issue.save
430 assert !issue.save
431 # Valid value
431 # Valid value
432 issue.custom_field_values = { field.id => 'PostgreSQL' }
432 issue.custom_field_values = { field.id => 'PostgreSQL' }
433 assert issue.save
433 assert issue.save
434 issue.reload
434 issue.reload
435 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
435 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
436 end
436 end
437
437
438 def test_should_not_update_attributes_if_custom_fields_validation_fails
438 def test_should_not_update_attributes_if_custom_fields_validation_fails
439 issue = Issue.find(1)
439 issue = Issue.find(1)
440 field = IssueCustomField.find_by_name('Database')
440 field = IssueCustomField.find_by_name('Database')
441 assert issue.available_custom_fields.include?(field)
441 assert issue.available_custom_fields.include?(field)
442
442
443 issue.custom_field_values = { field.id => 'Invalid' }
443 issue.custom_field_values = { field.id => 'Invalid' }
444 issue.subject = 'Should be not be saved'
444 issue.subject = 'Should be not be saved'
445 assert !issue.save
445 assert !issue.save
446
446
447 issue.reload
447 issue.reload
448 assert_equal "Cannot print recipes", issue.subject
448 assert_equal "Cannot print recipes", issue.subject
449 end
449 end
450
450
451 def test_should_not_recreate_custom_values_objects_on_update
451 def test_should_not_recreate_custom_values_objects_on_update
452 field = IssueCustomField.find_by_name('Database')
452 field = IssueCustomField.find_by_name('Database')
453
453
454 issue = Issue.find(1)
454 issue = Issue.find(1)
455 issue.custom_field_values = { field.id => 'PostgreSQL' }
455 issue.custom_field_values = { field.id => 'PostgreSQL' }
456 assert issue.save
456 assert issue.save
457 custom_value = issue.custom_value_for(field)
457 custom_value = issue.custom_value_for(field)
458 issue.reload
458 issue.reload
459 issue.custom_field_values = { field.id => 'MySQL' }
459 issue.custom_field_values = { field.id => 'MySQL' }
460 assert issue.save
460 assert issue.save
461 issue.reload
461 issue.reload
462 assert_equal custom_value.id, issue.custom_value_for(field).id
462 assert_equal custom_value.id, issue.custom_value_for(field).id
463 end
463 end
464
464
465 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
465 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
466 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
466 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
467 :status_id => 1, :subject => 'Test',
467 :status_id => 1, :subject => 'Test',
468 :custom_field_values => {'2' => 'Test'})
468 :custom_field_values => {'2' => 'Test'})
469 assert !Tracker.find(2).custom_field_ids.include?(2)
469 assert !Tracker.find(2).custom_field_ids.include?(2)
470
470
471 issue = Issue.find(issue.id)
471 issue = Issue.find(issue.id)
472 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
472 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
473
473
474 issue = Issue.find(issue.id)
474 issue = Issue.find(issue.id)
475 custom_value = issue.custom_value_for(2)
475 custom_value = issue.custom_value_for(2)
476 assert_not_nil custom_value
476 assert_not_nil custom_value
477 assert_equal 'Test', custom_value.value
477 assert_equal 'Test', custom_value.value
478 end
478 end
479
479
480 def test_assigning_tracker_id_should_reload_custom_fields_values
480 def test_assigning_tracker_id_should_reload_custom_fields_values
481 issue = Issue.new(:project => Project.find(1))
481 issue = Issue.new(:project => Project.find(1))
482 assert issue.custom_field_values.empty?
482 assert issue.custom_field_values.empty?
483 issue.tracker_id = 1
483 issue.tracker_id = 1
484 assert issue.custom_field_values.any?
484 assert issue.custom_field_values.any?
485 end
485 end
486
486
487 def test_assigning_attributes_should_assign_project_and_tracker_first
487 def test_assigning_attributes_should_assign_project_and_tracker_first
488 seq = sequence('seq')
488 seq = sequence('seq')
489 issue = Issue.new
489 issue = Issue.new
490 issue.expects(:project_id=).in_sequence(seq)
490 issue.expects(:project_id=).in_sequence(seq)
491 issue.expects(:tracker_id=).in_sequence(seq)
491 issue.expects(:tracker_id=).in_sequence(seq)
492 issue.expects(:subject=).in_sequence(seq)
492 issue.expects(:subject=).in_sequence(seq)
493 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
493 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
494 end
494 end
495
495
496 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
496 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
497 attributes = ActiveSupport::OrderedHash.new
497 attributes = ActiveSupport::OrderedHash.new
498 attributes['custom_field_values'] = { '1' => 'MySQL' }
498 attributes['custom_field_values'] = { '1' => 'MySQL' }
499 attributes['tracker_id'] = '1'
499 attributes['tracker_id'] = '1'
500 issue = Issue.new(:project => Project.find(1))
500 issue = Issue.new(:project => Project.find(1))
501 issue.attributes = attributes
501 issue.attributes = attributes
502 assert_equal 'MySQL', issue.custom_field_value(1)
502 assert_equal 'MySQL', issue.custom_field_value(1)
503 end
503 end
504
504
505 def test_reload_should_reload_custom_field_values
505 def test_reload_should_reload_custom_field_values
506 issue = Issue.generate!
506 issue = Issue.generate!
507 issue.custom_field_values = {'2' => 'Foo'}
507 issue.custom_field_values = {'2' => 'Foo'}
508 issue.save!
508 issue.save!
509
509
510 issue = Issue.order('id desc').first
510 issue = Issue.order('id desc').first
511 assert_equal 'Foo', issue.custom_field_value(2)
511 assert_equal 'Foo', issue.custom_field_value(2)
512
512
513 issue.custom_field_values = {'2' => 'Bar'}
513 issue.custom_field_values = {'2' => 'Bar'}
514 assert_equal 'Bar', issue.custom_field_value(2)
514 assert_equal 'Bar', issue.custom_field_value(2)
515
515
516 issue.reload
516 issue.reload
517 assert_equal 'Foo', issue.custom_field_value(2)
517 assert_equal 'Foo', issue.custom_field_value(2)
518 end
518 end
519
519
520 def test_should_update_issue_with_disabled_tracker
520 def test_should_update_issue_with_disabled_tracker
521 p = Project.find(1)
521 p = Project.find(1)
522 issue = Issue.find(1)
522 issue = Issue.find(1)
523
523
524 p.trackers.delete(issue.tracker)
524 p.trackers.delete(issue.tracker)
525 assert !p.trackers.include?(issue.tracker)
525 assert !p.trackers.include?(issue.tracker)
526
526
527 issue.reload
527 issue.reload
528 issue.subject = 'New subject'
528 issue.subject = 'New subject'
529 assert issue.save
529 assert issue.save
530 end
530 end
531
531
532 def test_should_not_set_a_disabled_tracker
532 def test_should_not_set_a_disabled_tracker
533 p = Project.find(1)
533 p = Project.find(1)
534 p.trackers.delete(Tracker.find(2))
534 p.trackers.delete(Tracker.find(2))
535
535
536 issue = Issue.find(1)
536 issue = Issue.find(1)
537 issue.tracker_id = 2
537 issue.tracker_id = 2
538 issue.subject = 'New subject'
538 issue.subject = 'New subject'
539 assert !issue.save
539 assert !issue.save
540 assert_not_equal [], issue.errors[:tracker_id]
540 assert_not_equal [], issue.errors[:tracker_id]
541 end
541 end
542
542
543 def test_category_based_assignment
543 def test_category_based_assignment
544 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
544 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
545 :status_id => 1, :priority => IssuePriority.all.first,
545 :status_id => 1, :priority => IssuePriority.all.first,
546 :subject => 'Assignment test',
546 :subject => 'Assignment test',
547 :description => 'Assignment test', :category_id => 1)
547 :description => 'Assignment test', :category_id => 1)
548 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
548 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
549 end
549 end
550
550
551 def test_new_statuses_allowed_to
551 def test_new_statuses_allowed_to
552 WorkflowTransition.delete_all
552 WorkflowTransition.delete_all
553 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
553 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
554 :old_status_id => 1, :new_status_id => 2,
554 :old_status_id => 1, :new_status_id => 2,
555 :author => false, :assignee => false)
555 :author => false, :assignee => false)
556 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
556 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
557 :old_status_id => 1, :new_status_id => 3,
557 :old_status_id => 1, :new_status_id => 3,
558 :author => true, :assignee => false)
558 :author => true, :assignee => false)
559 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
559 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
560 :old_status_id => 1, :new_status_id => 4,
560 :old_status_id => 1, :new_status_id => 4,
561 :author => false, :assignee => true)
561 :author => false, :assignee => true)
562 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
562 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
563 :old_status_id => 1, :new_status_id => 5,
563 :old_status_id => 1, :new_status_id => 5,
564 :author => true, :assignee => true)
564 :author => true, :assignee => true)
565 status = IssueStatus.find(1)
565 status = IssueStatus.find(1)
566 role = Role.find(1)
566 role = Role.find(1)
567 tracker = Tracker.find(1)
567 tracker = Tracker.find(1)
568 user = User.find(2)
568 user = User.find(2)
569
569
570 issue = Issue.generate!(:tracker => tracker, :status => status,
570 issue = Issue.generate!(:tracker => tracker, :status => status,
571 :project_id => 1, :author_id => 1)
571 :project_id => 1, :author_id => 1)
572 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
572 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
573
573
574 issue = Issue.generate!(:tracker => tracker, :status => status,
574 issue = Issue.generate!(:tracker => tracker, :status => status,
575 :project_id => 1, :author => user)
575 :project_id => 1, :author => user)
576 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
576 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
577
577
578 issue = Issue.generate!(:tracker => tracker, :status => status,
578 issue = Issue.generate!(:tracker => tracker, :status => status,
579 :project_id => 1, :author_id => 1,
579 :project_id => 1, :author_id => 1,
580 :assigned_to => user)
580 :assigned_to => user)
581 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
581 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
582
582
583 issue = Issue.generate!(:tracker => tracker, :status => status,
583 issue = Issue.generate!(:tracker => tracker, :status => status,
584 :project_id => 1, :author => user,
584 :project_id => 1, :author => user,
585 :assigned_to => user)
585 :assigned_to => user)
586 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
586 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
587
587
588 group = Group.generate!
588 group = Group.generate!
589 group.users << user
589 group.users << user
590 issue = Issue.generate!(:tracker => tracker, :status => status,
590 issue = Issue.generate!(:tracker => tracker, :status => status,
591 :project_id => 1, :author => user,
591 :project_id => 1, :author => user,
592 :assigned_to => group)
592 :assigned_to => group)
593 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
593 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
594 end
594 end
595
595
596 def test_new_statuses_allowed_to_should_consider_group_assignment
596 def test_new_statuses_allowed_to_should_consider_group_assignment
597 WorkflowTransition.delete_all
597 WorkflowTransition.delete_all
598 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
598 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
599 :old_status_id => 1, :new_status_id => 4,
599 :old_status_id => 1, :new_status_id => 4,
600 :author => false, :assignee => true)
600 :author => false, :assignee => true)
601 user = User.find(2)
601 user = User.find(2)
602 group = Group.generate!
602 group = Group.generate!
603 group.users << user
603 group.users << user
604
604
605 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
605 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
606 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
606 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
607 end
607 end
608
608
609 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
609 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
610 admin = User.find(1)
610 admin = User.find(1)
611 issue = Issue.find(1)
611 issue = Issue.find(1)
612 assert !admin.member_of?(issue.project)
612 assert !admin.member_of?(issue.project)
613 expected_statuses = [issue.status] +
613 expected_statuses = [issue.status] +
614 WorkflowTransition.where(:old_status_id => issue.status_id).
614 WorkflowTransition.where(:old_status_id => issue.status_id).
615 map(&:new_status).uniq.sort
615 map(&:new_status).uniq.sort
616 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
616 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
617 end
617 end
618
618
619 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
619 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
620 issue = Issue.find(1).copy
620 issue = Issue.find(1).copy
621 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
621 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
622
622
623 issue = Issue.find(2).copy
623 issue = Issue.find(2).copy
624 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
624 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
625 end
625 end
626
626
627 def test_safe_attributes_names_should_not_include_disabled_field
627 def test_safe_attributes_names_should_not_include_disabled_field
628 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
628 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
629
629
630 issue = Issue.new(:tracker => tracker)
630 issue = Issue.new(:tracker => tracker)
631 assert_include 'tracker_id', issue.safe_attribute_names
631 assert_include 'tracker_id', issue.safe_attribute_names
632 assert_include 'status_id', issue.safe_attribute_names
632 assert_include 'status_id', issue.safe_attribute_names
633 assert_include 'subject', issue.safe_attribute_names
633 assert_include 'subject', issue.safe_attribute_names
634 assert_include 'description', issue.safe_attribute_names
634 assert_include 'description', issue.safe_attribute_names
635 assert_include 'custom_field_values', issue.safe_attribute_names
635 assert_include 'custom_field_values', issue.safe_attribute_names
636 assert_include 'custom_fields', issue.safe_attribute_names
636 assert_include 'custom_fields', issue.safe_attribute_names
637 assert_include 'lock_version', issue.safe_attribute_names
637 assert_include 'lock_version', issue.safe_attribute_names
638
638
639 tracker.core_fields.each do |field|
639 tracker.core_fields.each do |field|
640 assert_include field, issue.safe_attribute_names
640 assert_include field, issue.safe_attribute_names
641 end
641 end
642
642
643 tracker.disabled_core_fields.each do |field|
643 tracker.disabled_core_fields.each do |field|
644 assert_not_include field, issue.safe_attribute_names
644 assert_not_include field, issue.safe_attribute_names
645 end
645 end
646 end
646 end
647
647
648 def test_safe_attributes_should_ignore_disabled_fields
648 def test_safe_attributes_should_ignore_disabled_fields
649 tracker = Tracker.find(1)
649 tracker = Tracker.find(1)
650 tracker.core_fields = %w(assigned_to_id due_date)
650 tracker.core_fields = %w(assigned_to_id due_date)
651 tracker.save!
651 tracker.save!
652
652
653 issue = Issue.new(:tracker => tracker)
653 issue = Issue.new(:tracker => tracker)
654 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
654 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
655 assert_nil issue.start_date
655 assert_nil issue.start_date
656 assert_equal Date.parse('2012-07-14'), issue.due_date
656 assert_equal Date.parse('2012-07-14'), issue.due_date
657 end
657 end
658
658
659 def test_safe_attributes_should_accept_target_tracker_enabled_fields
659 def test_safe_attributes_should_accept_target_tracker_enabled_fields
660 source = Tracker.find(1)
660 source = Tracker.find(1)
661 source.core_fields = []
661 source.core_fields = []
662 source.save!
662 source.save!
663 target = Tracker.find(2)
663 target = Tracker.find(2)
664 target.core_fields = %w(assigned_to_id due_date)
664 target.core_fields = %w(assigned_to_id due_date)
665 target.save!
665 target.save!
666
666
667 issue = Issue.new(:tracker => source)
667 issue = Issue.new(:tracker => source)
668 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
668 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
669 assert_equal target, issue.tracker
669 assert_equal target, issue.tracker
670 assert_equal Date.parse('2012-07-14'), issue.due_date
670 assert_equal Date.parse('2012-07-14'), issue.due_date
671 end
671 end
672
672
673 def test_safe_attributes_should_not_include_readonly_fields
673 def test_safe_attributes_should_not_include_readonly_fields
674 WorkflowPermission.delete_all
674 WorkflowPermission.delete_all
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
676 :role_id => 1, :field_name => 'due_date',
676 :role_id => 1, :field_name => 'due_date',
677 :rule => 'readonly')
677 :rule => 'readonly')
678 user = User.find(2)
678 user = User.find(2)
679
679
680 issue = Issue.new(:project_id => 1, :tracker_id => 1)
680 issue = Issue.new(:project_id => 1, :tracker_id => 1)
681 assert_equal %w(due_date), issue.read_only_attribute_names(user)
681 assert_equal %w(due_date), issue.read_only_attribute_names(user)
682 assert_not_include 'due_date', issue.safe_attribute_names(user)
682 assert_not_include 'due_date', issue.safe_attribute_names(user)
683
683
684 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
684 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
685 assert_equal Date.parse('2012-07-14'), issue.start_date
685 assert_equal Date.parse('2012-07-14'), issue.start_date
686 assert_nil issue.due_date
686 assert_nil issue.due_date
687 end
687 end
688
688
689 def test_safe_attributes_should_not_include_readonly_custom_fields
689 def test_safe_attributes_should_not_include_readonly_custom_fields
690 cf1 = IssueCustomField.create!(:name => 'Writable field',
690 cf1 = IssueCustomField.create!(:name => 'Writable field',
691 :field_format => 'string',
691 :field_format => 'string',
692 :is_for_all => true, :tracker_ids => [1])
692 :is_for_all => true, :tracker_ids => [1])
693 cf2 = IssueCustomField.create!(:name => 'Readonly field',
693 cf2 = IssueCustomField.create!(:name => 'Readonly field',
694 :field_format => 'string',
694 :field_format => 'string',
695 :is_for_all => true, :tracker_ids => [1])
695 :is_for_all => true, :tracker_ids => [1])
696 WorkflowPermission.delete_all
696 WorkflowPermission.delete_all
697 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
697 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
698 :role_id => 1, :field_name => cf2.id.to_s,
698 :role_id => 1, :field_name => cf2.id.to_s,
699 :rule => 'readonly')
699 :rule => 'readonly')
700 user = User.find(2)
700 user = User.find(2)
701 issue = Issue.new(:project_id => 1, :tracker_id => 1)
701 issue = Issue.new(:project_id => 1, :tracker_id => 1)
702 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
702 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
703 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
703 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
704
704
705 issue.send :safe_attributes=, {'custom_field_values' => {
705 issue.send :safe_attributes=, {'custom_field_values' => {
706 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
706 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
707 }}, user
707 }}, user
708 assert_equal 'value1', issue.custom_field_value(cf1)
708 assert_equal 'value1', issue.custom_field_value(cf1)
709 assert_nil issue.custom_field_value(cf2)
709 assert_nil issue.custom_field_value(cf2)
710
710
711 issue.send :safe_attributes=, {'custom_fields' => [
711 issue.send :safe_attributes=, {'custom_fields' => [
712 {'id' => cf1.id.to_s, 'value' => 'valuea'},
712 {'id' => cf1.id.to_s, 'value' => 'valuea'},
713 {'id' => cf2.id.to_s, 'value' => 'valueb'}
713 {'id' => cf2.id.to_s, 'value' => 'valueb'}
714 ]}, user
714 ]}, user
715 assert_equal 'valuea', issue.custom_field_value(cf1)
715 assert_equal 'valuea', issue.custom_field_value(cf1)
716 assert_nil issue.custom_field_value(cf2)
716 assert_nil issue.custom_field_value(cf2)
717 end
717 end
718
718
719 def test_editable_custom_field_values_should_return_non_readonly_custom_values
719 def test_editable_custom_field_values_should_return_non_readonly_custom_values
720 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
720 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
721 :is_for_all => true, :tracker_ids => [1, 2])
721 :is_for_all => true, :tracker_ids => [1, 2])
722 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
722 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
723 :is_for_all => true, :tracker_ids => [1, 2])
723 :is_for_all => true, :tracker_ids => [1, 2])
724 WorkflowPermission.delete_all
724 WorkflowPermission.delete_all
725 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
725 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
726 :field_name => cf2.id.to_s, :rule => 'readonly')
726 :field_name => cf2.id.to_s, :rule => 'readonly')
727 user = User.find(2)
727 user = User.find(2)
728
728
729 issue = Issue.new(:project_id => 1, :tracker_id => 1)
729 issue = Issue.new(:project_id => 1, :tracker_id => 1)
730 values = issue.editable_custom_field_values(user)
730 values = issue.editable_custom_field_values(user)
731 assert values.detect {|value| value.custom_field == cf1}
731 assert values.detect {|value| value.custom_field == cf1}
732 assert_nil values.detect {|value| value.custom_field == cf2}
732 assert_nil values.detect {|value| value.custom_field == cf2}
733
733
734 issue.tracker_id = 2
734 issue.tracker_id = 2
735 values = issue.editable_custom_field_values(user)
735 values = issue.editable_custom_field_values(user)
736 assert values.detect {|value| value.custom_field == cf1}
736 assert values.detect {|value| value.custom_field == cf1}
737 assert values.detect {|value| value.custom_field == cf2}
737 assert values.detect {|value| value.custom_field == cf2}
738 end
738 end
739
739
740 def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only
740 def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only
741 enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2])
741 enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2])
742 disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2])
742 disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2])
743 user = User.find(2)
743 user = User.find(2)
744 issue = Issue.new(:project_id => 1, :tracker_id => 1)
744 issue = Issue.new(:project_id => 1, :tracker_id => 1)
745
745
746 assert_include enabled_cf, issue.editable_custom_fields(user)
746 assert_include enabled_cf, issue.editable_custom_fields(user)
747 assert_not_include disabled_cf, issue.editable_custom_fields(user)
747 assert_not_include disabled_cf, issue.editable_custom_fields(user)
748 end
748 end
749
749
750 def test_safe_attributes_should_accept_target_tracker_writable_fields
750 def test_safe_attributes_should_accept_target_tracker_writable_fields
751 WorkflowPermission.delete_all
751 WorkflowPermission.delete_all
752 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
752 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
753 :role_id => 1, :field_name => 'due_date',
753 :role_id => 1, :field_name => 'due_date',
754 :rule => 'readonly')
754 :rule => 'readonly')
755 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
755 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
756 :role_id => 1, :field_name => 'start_date',
756 :role_id => 1, :field_name => 'start_date',
757 :rule => 'readonly')
757 :rule => 'readonly')
758 user = User.find(2)
758 user = User.find(2)
759
759
760 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
760 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
761
761
762 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
762 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
763 'due_date' => '2012-07-14'}, user
763 'due_date' => '2012-07-14'}, user
764 assert_equal Date.parse('2012-07-12'), issue.start_date
764 assert_equal Date.parse('2012-07-12'), issue.start_date
765 assert_nil issue.due_date
765 assert_nil issue.due_date
766
766
767 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
767 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
768 'due_date' => '2012-07-16',
768 'due_date' => '2012-07-16',
769 'tracker_id' => 2}, user
769 'tracker_id' => 2}, user
770 assert_equal Date.parse('2012-07-12'), issue.start_date
770 assert_equal Date.parse('2012-07-12'), issue.start_date
771 assert_equal Date.parse('2012-07-16'), issue.due_date
771 assert_equal Date.parse('2012-07-16'), issue.due_date
772 end
772 end
773
773
774 def test_safe_attributes_should_accept_target_status_writable_fields
774 def test_safe_attributes_should_accept_target_status_writable_fields
775 WorkflowPermission.delete_all
775 WorkflowPermission.delete_all
776 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
776 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
777 :role_id => 1, :field_name => 'due_date',
777 :role_id => 1, :field_name => 'due_date',
778 :rule => 'readonly')
778 :rule => 'readonly')
779 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
779 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
780 :role_id => 1, :field_name => 'start_date',
780 :role_id => 1, :field_name => 'start_date',
781 :rule => 'readonly')
781 :rule => 'readonly')
782 user = User.find(2)
782 user = User.find(2)
783
783
784 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
784 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
785
785
786 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
786 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
787 'due_date' => '2012-07-14'},
787 'due_date' => '2012-07-14'},
788 user
788 user
789 assert_equal Date.parse('2012-07-12'), issue.start_date
789 assert_equal Date.parse('2012-07-12'), issue.start_date
790 assert_nil issue.due_date
790 assert_nil issue.due_date
791
791
792 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
792 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
793 'due_date' => '2012-07-16',
793 'due_date' => '2012-07-16',
794 'status_id' => 2},
794 'status_id' => 2},
795 user
795 user
796 assert_equal Date.parse('2012-07-12'), issue.start_date
796 assert_equal Date.parse('2012-07-12'), issue.start_date
797 assert_equal Date.parse('2012-07-16'), issue.due_date
797 assert_equal Date.parse('2012-07-16'), issue.due_date
798 end
798 end
799
799
800 def test_required_attributes_should_be_validated
800 def test_required_attributes_should_be_validated
801 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
801 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
802 :is_for_all => true, :tracker_ids => [1, 2])
802 :is_for_all => true, :tracker_ids => [1, 2])
803
803
804 WorkflowPermission.delete_all
804 WorkflowPermission.delete_all
805 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
805 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
806 :role_id => 1, :field_name => 'due_date',
806 :role_id => 1, :field_name => 'due_date',
807 :rule => 'required')
807 :rule => 'required')
808 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
808 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
809 :role_id => 1, :field_name => 'category_id',
809 :role_id => 1, :field_name => 'category_id',
810 :rule => 'required')
810 :rule => 'required')
811 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
811 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
812 :role_id => 1, :field_name => cf.id.to_s,
812 :role_id => 1, :field_name => cf.id.to_s,
813 :rule => 'required')
813 :rule => 'required')
814
814
815 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
815 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
816 :role_id => 1, :field_name => 'start_date',
816 :role_id => 1, :field_name => 'start_date',
817 :rule => 'required')
817 :rule => 'required')
818 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
818 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
819 :role_id => 1, :field_name => cf.id.to_s,
819 :role_id => 1, :field_name => cf.id.to_s,
820 :rule => 'required')
820 :rule => 'required')
821 user = User.find(2)
821 user = User.find(2)
822
822
823 issue = Issue.new(:project_id => 1, :tracker_id => 1,
823 issue = Issue.new(:project_id => 1, :tracker_id => 1,
824 :status_id => 1, :subject => 'Required fields',
824 :status_id => 1, :subject => 'Required fields',
825 :author => user)
825 :author => user)
826 assert_equal [cf.id.to_s, "category_id", "due_date"],
826 assert_equal [cf.id.to_s, "category_id", "due_date"],
827 issue.required_attribute_names(user).sort
827 issue.required_attribute_names(user).sort
828 assert !issue.save, "Issue was saved"
828 assert !issue.save, "Issue was saved"
829 assert_equal ["Category cannot be blank", "Due date cannot be blank", "Foo cannot be blank"],
829 assert_equal ["Category cannot be blank", "Due date cannot be blank", "Foo cannot be blank"],
830 issue.errors.full_messages.sort
830 issue.errors.full_messages.sort
831
831
832 issue.tracker_id = 2
832 issue.tracker_id = 2
833 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
833 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
834 assert !issue.save, "Issue was saved"
834 assert !issue.save, "Issue was saved"
835 assert_equal ["Foo cannot be blank", "Start date cannot be blank"],
835 assert_equal ["Foo cannot be blank", "Start date cannot be blank"],
836 issue.errors.full_messages.sort
836 issue.errors.full_messages.sort
837
837
838 issue.start_date = Date.today
838 issue.start_date = Date.today
839 issue.custom_field_values = {cf.id.to_s => 'bar'}
839 issue.custom_field_values = {cf.id.to_s => 'bar'}
840 assert issue.save
840 assert issue.save
841 end
841 end
842
842
843 def test_required_attribute_that_is_disabled_for_the_tracker_should_not_be_required
843 def test_required_attribute_that_is_disabled_for_the_tracker_should_not_be_required
844 WorkflowPermission.delete_all
844 WorkflowPermission.delete_all
845 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
845 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
846 :role_id => 1, :field_name => 'start_date',
846 :role_id => 1, :field_name => 'start_date',
847 :rule => 'required')
847 :rule => 'required')
848 user = User.find(2)
848 user = User.find(2)
849
849
850 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
850 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
851 :subject => 'Required fields', :author => user)
851 :subject => 'Required fields', :author => user)
852 assert !issue.save
852 assert !issue.save
853 assert_include "Start date cannot be blank", issue.errors.full_messages
853 assert_include "Start date cannot be blank", issue.errors.full_messages
854
854
855 tracker = Tracker.find(1)
855 tracker = Tracker.find(1)
856 tracker.core_fields -= %w(start_date)
856 tracker.core_fields -= %w(start_date)
857 tracker.save!
857 tracker.save!
858 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
858 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
859 :subject => 'Required fields', :author => user)
859 :subject => 'Required fields', :author => user)
860 assert issue.save
860 assert issue.save
861 end
861 end
862
862
863 def test_required_custom_field_that_is_not_visible_for_the_user_should_not_be_required
863 def test_required_custom_field_that_is_not_visible_for_the_user_should_not_be_required
864 CustomField.delete_all
864 CustomField.delete_all
865 field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true)
865 field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true)
866 user = User.generate!
866 user = User.generate!
867 User.add_to_project(user, Project.find(1), Role.find(2))
867 User.add_to_project(user, Project.find(1), Role.find(2))
868
868
869 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
869 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
870 :subject => 'Required fields', :author => user)
870 :subject => 'Required fields', :author => user)
871 assert_save issue
871 assert_save issue
872 end
872 end
873
873
874 def test_required_custom_field_that_is_visible_for_the_user_should_be_required
874 def test_required_custom_field_that_is_visible_for_the_user_should_be_required
875 CustomField.delete_all
875 CustomField.delete_all
876 field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true)
876 field = IssueCustomField.generate!(:is_required => true, :visible => false, :role_ids => [1], :trackers => Tracker.all, :is_for_all => true)
877 user = User.generate!
877 user = User.generate!
878 User.add_to_project(user, Project.find(1), Role.find(1))
878 User.add_to_project(user, Project.find(1), Role.find(1))
879
879
880 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
880 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
881 :subject => 'Required fields', :author => user)
881 :subject => 'Required fields', :author => user)
882 assert !issue.save
882 assert !issue.save
883 assert_include "#{field.name} cannot be blank", issue.errors.full_messages
883 assert_include "#{field.name} cannot be blank", issue.errors.full_messages
884 end
884 end
885
885
886 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
886 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
887 WorkflowPermission.delete_all
887 WorkflowPermission.delete_all
888 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
888 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
889 :role_id => 1, :field_name => 'due_date',
889 :role_id => 1, :field_name => 'due_date',
890 :rule => 'required')
890 :rule => 'required')
891 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
891 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
892 :role_id => 1, :field_name => 'start_date',
892 :role_id => 1, :field_name => 'start_date',
893 :rule => 'required')
893 :rule => 'required')
894 user = User.find(2)
894 user = User.find(2)
895 member = Member.find(1)
895 member = Member.find(1)
896 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
896 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
897
897
898 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
898 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
899
899
900 member.role_ids = [1, 2]
900 member.role_ids = [1, 2]
901 member.save!
901 member.save!
902 assert_equal [], issue.required_attribute_names(user.reload)
902 assert_equal [], issue.required_attribute_names(user.reload)
903
903
904 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
904 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
905 :role_id => 2, :field_name => 'due_date',
905 :role_id => 2, :field_name => 'due_date',
906 :rule => 'required')
906 :rule => 'required')
907 assert_equal %w(due_date), issue.required_attribute_names(user)
907 assert_equal %w(due_date), issue.required_attribute_names(user)
908
908
909 member.role_ids = [1, 2, 3]
909 member.role_ids = [1, 2, 3]
910 member.save!
910 member.save!
911 assert_equal [], issue.required_attribute_names(user.reload)
911 assert_equal [], issue.required_attribute_names(user.reload)
912
912
913 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
913 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
914 :role_id => 3, :field_name => 'due_date',
914 :role_id => 3, :field_name => 'due_date',
915 :rule => 'readonly')
915 :rule => 'readonly')
916 # required + readonly => required
916 # required + readonly => required
917 assert_equal %w(due_date), issue.required_attribute_names(user)
917 assert_equal %w(due_date), issue.required_attribute_names(user)
918 end
918 end
919
919
920 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
920 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
921 WorkflowPermission.delete_all
921 WorkflowPermission.delete_all
922 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
922 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
923 :role_id => 1, :field_name => 'due_date',
923 :role_id => 1, :field_name => 'due_date',
924 :rule => 'readonly')
924 :rule => 'readonly')
925 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
925 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
926 :role_id => 1, :field_name => 'start_date',
926 :role_id => 1, :field_name => 'start_date',
927 :rule => 'readonly')
927 :rule => 'readonly')
928 user = User.find(2)
928 user = User.find(2)
929 member = Member.find(1)
929 member = Member.find(1)
930 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
930 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
931
931
932 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
932 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
933
933
934 member.role_ids = [1, 2]
934 member.role_ids = [1, 2]
935 member.save!
935 member.save!
936 assert_equal [], issue.read_only_attribute_names(user.reload)
936 assert_equal [], issue.read_only_attribute_names(user.reload)
937
937
938 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
938 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
939 :role_id => 2, :field_name => 'due_date',
939 :role_id => 2, :field_name => 'due_date',
940 :rule => 'readonly')
940 :rule => 'readonly')
941 assert_equal %w(due_date), issue.read_only_attribute_names(user)
941 assert_equal %w(due_date), issue.read_only_attribute_names(user)
942 end
942 end
943
943
944 # A field that is not visible by role 2 and readonly by role 1 should be readonly for user with role 1 and 2
944 # A field that is not visible by role 2 and readonly by role 1 should be readonly for user with role 1 and 2
945 def test_read_only_attribute_names_should_include_custom_fields_that_combine_readonly_and_not_visible_for_roles
945 def test_read_only_attribute_names_should_include_custom_fields_that_combine_readonly_and_not_visible_for_roles
946 field = IssueCustomField.generate!(
946 field = IssueCustomField.generate!(
947 :is_for_all => true, :trackers => Tracker.all, :visible => false, :role_ids => [1]
947 :is_for_all => true, :trackers => Tracker.all, :visible => false, :role_ids => [1]
948 )
948 )
949 WorkflowPermission.delete_all
949 WorkflowPermission.delete_all
950 WorkflowPermission.create!(
950 WorkflowPermission.create!(
951 :old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => field.id, :rule => 'readonly'
951 :old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => field.id, :rule => 'readonly'
952 )
952 )
953 user = User.generate!
953 user = User.generate!
954 project = Project.find(1)
954 project = Project.find(1)
955 User.add_to_project(user, project, Role.where(:id => [1, 2]))
955 User.add_to_project(user, project, Role.where(:id => [1, 2]))
956
956
957 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
957 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
958 assert_equal [field.id.to_s], issue.read_only_attribute_names(user)
958 assert_equal [field.id.to_s], issue.read_only_attribute_names(user)
959 end
959 end
960
960
961 def test_workflow_rules_should_ignore_roles_without_issue_permissions
961 def test_workflow_rules_should_ignore_roles_without_issue_permissions
962 role = Role.generate! :permissions => [:view_issues, :edit_issues]
962 role = Role.generate! :permissions => [:view_issues, :edit_issues]
963 ignored_role = Role.generate! :permissions => [:view_issues]
963 ignored_role = Role.generate! :permissions => [:view_issues]
964
964
965 WorkflowPermission.delete_all
965 WorkflowPermission.delete_all
966 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
966 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
967 :role => role, :field_name => 'due_date',
967 :role => role, :field_name => 'due_date',
968 :rule => 'required')
968 :rule => 'required')
969 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
969 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
970 :role => role, :field_name => 'start_date',
970 :role => role, :field_name => 'start_date',
971 :rule => 'readonly')
971 :rule => 'readonly')
972 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
972 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
973 :role => role, :field_name => 'done_ratio',
973 :role => role, :field_name => 'done_ratio',
974 :rule => 'readonly')
974 :rule => 'readonly')
975 user = User.generate!
975 user = User.generate!
976 User.add_to_project user, Project.find(1), [role, ignored_role]
976 User.add_to_project user, Project.find(1), [role, ignored_role]
977
977
978 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
978 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
979
979
980 assert_equal %w(due_date), issue.required_attribute_names(user)
980 assert_equal %w(due_date), issue.required_attribute_names(user)
981 assert_equal %w(done_ratio start_date), issue.read_only_attribute_names(user).sort
981 assert_equal %w(done_ratio start_date), issue.read_only_attribute_names(user).sort
982 end
982 end
983
983
984 def test_workflow_rules_should_work_for_member_with_duplicate_role
985 WorkflowPermission.delete_all
986 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
987 :role_id => 1, :field_name => 'due_date',
988 :rule => 'required')
989 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
990 :role_id => 1, :field_name => 'start_date',
991 :rule => 'readonly')
992
993 user = User.generate!
994 m = Member.new(:user_id => user.id, :project_id => 1)
995 m.member_roles.build(:role_id => 1)
996 m.member_roles.build(:role_id => 1)
997 m.save!
998
999 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
1000
1001 assert_equal %w(due_date), issue.required_attribute_names(user)
1002 assert_equal %w(start_date), issue.read_only_attribute_names(user)
1003 end
1004
984 def test_copy
1005 def test_copy
985 issue = Issue.new.copy_from(1)
1006 issue = Issue.new.copy_from(1)
986 assert issue.copy?
1007 assert issue.copy?
987 assert issue.save
1008 assert issue.save
988 issue.reload
1009 issue.reload
989 orig = Issue.find(1)
1010 orig = Issue.find(1)
990 assert_equal orig.subject, issue.subject
1011 assert_equal orig.subject, issue.subject
991 assert_equal orig.tracker, issue.tracker
1012 assert_equal orig.tracker, issue.tracker
992 assert_equal "125", issue.custom_value_for(2).value
1013 assert_equal "125", issue.custom_value_for(2).value
993 end
1014 end
994
1015
995 def test_copy_should_copy_status
1016 def test_copy_should_copy_status
996 orig = Issue.find(8)
1017 orig = Issue.find(8)
997 assert orig.status != orig.default_status
1018 assert orig.status != orig.default_status
998
1019
999 issue = Issue.new.copy_from(orig)
1020 issue = Issue.new.copy_from(orig)
1000 assert issue.save
1021 assert issue.save
1001 issue.reload
1022 issue.reload
1002 assert_equal orig.status, issue.status
1023 assert_equal orig.status, issue.status
1003 end
1024 end
1004
1025
1005 def test_copy_should_add_relation_with_copied_issue
1026 def test_copy_should_add_relation_with_copied_issue
1006 copied = Issue.find(1)
1027 copied = Issue.find(1)
1007 issue = Issue.new.copy_from(copied)
1028 issue = Issue.new.copy_from(copied)
1008 assert issue.save
1029 assert issue.save
1009 issue.reload
1030 issue.reload
1010
1031
1011 assert_equal 1, issue.relations.size
1032 assert_equal 1, issue.relations.size
1012 relation = issue.relations.first
1033 relation = issue.relations.first
1013 assert_equal 'copied_to', relation.relation_type
1034 assert_equal 'copied_to', relation.relation_type
1014 assert_equal copied, relation.issue_from
1035 assert_equal copied, relation.issue_from
1015 assert_equal issue, relation.issue_to
1036 assert_equal issue, relation.issue_to
1016 end
1037 end
1017
1038
1018 def test_copy_should_copy_subtasks
1039 def test_copy_should_copy_subtasks
1019 issue = Issue.generate_with_descendants!
1040 issue = Issue.generate_with_descendants!
1020
1041
1021 copy = issue.reload.copy
1042 copy = issue.reload.copy
1022 copy.author = User.find(7)
1043 copy.author = User.find(7)
1023 assert_difference 'Issue.count', 1+issue.descendants.count do
1044 assert_difference 'Issue.count', 1+issue.descendants.count do
1024 assert copy.save
1045 assert copy.save
1025 end
1046 end
1026 copy.reload
1047 copy.reload
1027 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
1048 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
1028 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
1049 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
1029 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
1050 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
1030 assert_equal copy.author, child_copy.author
1051 assert_equal copy.author, child_copy.author
1031 end
1052 end
1032
1053
1033 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
1054 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
1034 parent = Issue.generate!
1055 parent = Issue.generate!
1035 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1056 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1036 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1057 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1037
1058
1038 copy = parent.reload.copy
1059 copy = parent.reload.copy
1039 copy.parent_issue_id = parent.id
1060 copy.parent_issue_id = parent.id
1040 copy.author = User.find(7)
1061 copy.author = User.find(7)
1041 assert_difference 'Issue.count', 3 do
1062 assert_difference 'Issue.count', 3 do
1042 assert copy.save
1063 assert copy.save
1043 end
1064 end
1044 parent.reload
1065 parent.reload
1045 copy.reload
1066 copy.reload
1046 assert_equal parent, copy.parent
1067 assert_equal parent, copy.parent
1047 assert_equal 3, parent.children.count
1068 assert_equal 3, parent.children.count
1048 assert_equal 5, parent.descendants.count
1069 assert_equal 5, parent.descendants.count
1049 assert_equal 2, copy.children.count
1070 assert_equal 2, copy.children.count
1050 assert_equal 2, copy.descendants.count
1071 assert_equal 2, copy.descendants.count
1051 end
1072 end
1052
1073
1053 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
1074 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
1054 parent = Issue.generate!
1075 parent = Issue.generate!
1055 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1076 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1056 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1077 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1057
1078
1058 copy = parent.reload.copy
1079 copy = parent.reload.copy
1059 copy.parent_issue_id = child1.id
1080 copy.parent_issue_id = child1.id
1060 copy.author = User.find(7)
1081 copy.author = User.find(7)
1061 assert_difference 'Issue.count', 3 do
1082 assert_difference 'Issue.count', 3 do
1062 assert copy.save
1083 assert copy.save
1063 end
1084 end
1064 parent.reload
1085 parent.reload
1065 child1.reload
1086 child1.reload
1066 copy.reload
1087 copy.reload
1067 assert_equal child1, copy.parent
1088 assert_equal child1, copy.parent
1068 assert_equal 2, parent.children.count
1089 assert_equal 2, parent.children.count
1069 assert_equal 5, parent.descendants.count
1090 assert_equal 5, parent.descendants.count
1070 assert_equal 1, child1.children.count
1091 assert_equal 1, child1.children.count
1071 assert_equal 3, child1.descendants.count
1092 assert_equal 3, child1.descendants.count
1072 assert_equal 2, copy.children.count
1093 assert_equal 2, copy.children.count
1073 assert_equal 2, copy.descendants.count
1094 assert_equal 2, copy.descendants.count
1074 end
1095 end
1075
1096
1076 def test_copy_should_copy_subtasks_to_target_project
1097 def test_copy_should_copy_subtasks_to_target_project
1077 issue = Issue.generate_with_descendants!
1098 issue = Issue.generate_with_descendants!
1078
1099
1079 copy = issue.copy(:project_id => 3)
1100 copy = issue.copy(:project_id => 3)
1080 assert_difference 'Issue.count', 1+issue.descendants.count do
1101 assert_difference 'Issue.count', 1+issue.descendants.count do
1081 assert copy.save
1102 assert copy.save
1082 end
1103 end
1083 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
1104 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
1084 end
1105 end
1085
1106
1086 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
1107 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
1087 issue = Issue.generate_with_descendants!
1108 issue = Issue.generate_with_descendants!
1088
1109
1089 copy = issue.reload.copy
1110 copy = issue.reload.copy
1090 assert_difference 'Issue.count', 1+issue.descendants.count do
1111 assert_difference 'Issue.count', 1+issue.descendants.count do
1091 assert copy.save
1112 assert copy.save
1092 assert copy.save
1113 assert copy.save
1093 end
1114 end
1094 end
1115 end
1095
1116
1096 def test_should_not_call_after_project_change_on_creation
1117 def test_should_not_call_after_project_change_on_creation
1097 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
1118 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
1098 :subject => 'Test', :author_id => 1)
1119 :subject => 'Test', :author_id => 1)
1099 issue.expects(:after_project_change).never
1120 issue.expects(:after_project_change).never
1100 issue.save!
1121 issue.save!
1101 end
1122 end
1102
1123
1103 def test_should_not_call_after_project_change_on_update
1124 def test_should_not_call_after_project_change_on_update
1104 issue = Issue.find(1)
1125 issue = Issue.find(1)
1105 issue.project = Project.find(1)
1126 issue.project = Project.find(1)
1106 issue.subject = 'No project change'
1127 issue.subject = 'No project change'
1107 issue.expects(:after_project_change).never
1128 issue.expects(:after_project_change).never
1108 issue.save!
1129 issue.save!
1109 end
1130 end
1110
1131
1111 def test_should_call_after_project_change_on_project_change
1132 def test_should_call_after_project_change_on_project_change
1112 issue = Issue.find(1)
1133 issue = Issue.find(1)
1113 issue.project = Project.find(2)
1134 issue.project = Project.find(2)
1114 issue.expects(:after_project_change).once
1135 issue.expects(:after_project_change).once
1115 issue.save!
1136 issue.save!
1116 end
1137 end
1117
1138
1118 def test_adding_journal_should_update_timestamp
1139 def test_adding_journal_should_update_timestamp
1119 issue = Issue.find(1)
1140 issue = Issue.find(1)
1120 updated_on_was = issue.updated_on
1141 updated_on_was = issue.updated_on
1121
1142
1122 issue.init_journal(User.first, "Adding notes")
1143 issue.init_journal(User.first, "Adding notes")
1123 assert_difference 'Journal.count' do
1144 assert_difference 'Journal.count' do
1124 assert issue.save
1145 assert issue.save
1125 end
1146 end
1126 issue.reload
1147 issue.reload
1127
1148
1128 assert_not_equal updated_on_was, issue.updated_on
1149 assert_not_equal updated_on_was, issue.updated_on
1129 end
1150 end
1130
1151
1131 def test_should_close_duplicates
1152 def test_should_close_duplicates
1132 # Create 3 issues
1153 # Create 3 issues
1133 issue1 = Issue.generate!
1154 issue1 = Issue.generate!
1134 issue2 = Issue.generate!
1155 issue2 = Issue.generate!
1135 issue3 = Issue.generate!
1156 issue3 = Issue.generate!
1136
1157
1137 # 2 is a dupe of 1
1158 # 2 is a dupe of 1
1138 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
1159 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
1139 :relation_type => IssueRelation::TYPE_DUPLICATES)
1160 :relation_type => IssueRelation::TYPE_DUPLICATES)
1140 # And 3 is a dupe of 2
1161 # And 3 is a dupe of 2
1141 # IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1162 # IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1142 # :relation_type => IssueRelation::TYPE_DUPLICATES)
1163 # :relation_type => IssueRelation::TYPE_DUPLICATES)
1143 # And 3 is a dupe of 1 (circular duplicates)
1164 # And 3 is a dupe of 1 (circular duplicates)
1144 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
1165 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
1145 :relation_type => IssueRelation::TYPE_DUPLICATES)
1166 :relation_type => IssueRelation::TYPE_DUPLICATES)
1146
1167
1147 assert issue1.reload.duplicates.include?(issue2)
1168 assert issue1.reload.duplicates.include?(issue2)
1148
1169
1149 # Closing issue 1
1170 # Closing issue 1
1150 issue1.init_journal(User.first, "Closing issue1")
1171 issue1.init_journal(User.first, "Closing issue1")
1151 issue1.status = IssueStatus.where(:is_closed => true).first
1172 issue1.status = IssueStatus.where(:is_closed => true).first
1152 assert issue1.save
1173 assert issue1.save
1153 # 2 and 3 should be also closed
1174 # 2 and 3 should be also closed
1154 assert issue2.reload.closed?
1175 assert issue2.reload.closed?
1155 assert issue3.reload.closed?
1176 assert issue3.reload.closed?
1156 end
1177 end
1157
1178
1158 def test_should_not_close_duplicated_issue
1179 def test_should_not_close_duplicated_issue
1159 issue1 = Issue.generate!
1180 issue1 = Issue.generate!
1160 issue2 = Issue.generate!
1181 issue2 = Issue.generate!
1161
1182
1162 # 2 is a dupe of 1
1183 # 2 is a dupe of 1
1163 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1184 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1164 :relation_type => IssueRelation::TYPE_DUPLICATES)
1185 :relation_type => IssueRelation::TYPE_DUPLICATES)
1165 # 2 is a dup of 1 but 1 is not a duplicate of 2
1186 # 2 is a dup of 1 but 1 is not a duplicate of 2
1166 assert !issue2.reload.duplicates.include?(issue1)
1187 assert !issue2.reload.duplicates.include?(issue1)
1167
1188
1168 # Closing issue 2
1189 # Closing issue 2
1169 issue2.init_journal(User.first, "Closing issue2")
1190 issue2.init_journal(User.first, "Closing issue2")
1170 issue2.status = IssueStatus.where(:is_closed => true).first
1191 issue2.status = IssueStatus.where(:is_closed => true).first
1171 assert issue2.save
1192 assert issue2.save
1172 # 1 should not be also closed
1193 # 1 should not be also closed
1173 assert !issue1.reload.closed?
1194 assert !issue1.reload.closed?
1174 end
1195 end
1175
1196
1176 def test_assignable_versions
1197 def test_assignable_versions
1177 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1198 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1178 :status_id => 1, :fixed_version_id => 1,
1199 :status_id => 1, :fixed_version_id => 1,
1179 :subject => 'New issue')
1200 :subject => 'New issue')
1180 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1201 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1181 end
1202 end
1182
1203
1183 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1204 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1184 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1205 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1185 :status_id => 1, :fixed_version_id => 1,
1206 :status_id => 1, :fixed_version_id => 1,
1186 :subject => 'New issue')
1207 :subject => 'New issue')
1187 assert !issue.save
1208 assert !issue.save
1188 assert_not_equal [], issue.errors[:fixed_version_id]
1209 assert_not_equal [], issue.errors[:fixed_version_id]
1189 end
1210 end
1190
1211
1191 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1212 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1192 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1213 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1193 :status_id => 1, :fixed_version_id => 2,
1214 :status_id => 1, :fixed_version_id => 2,
1194 :subject => 'New issue')
1215 :subject => 'New issue')
1195 assert !issue.save
1216 assert !issue.save
1196 assert_not_equal [], issue.errors[:fixed_version_id]
1217 assert_not_equal [], issue.errors[:fixed_version_id]
1197 end
1218 end
1198
1219
1199 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1220 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1200 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1221 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1201 :status_id => 1, :fixed_version_id => 3,
1222 :status_id => 1, :fixed_version_id => 3,
1202 :subject => 'New issue')
1223 :subject => 'New issue')
1203 assert issue.save
1224 assert issue.save
1204 end
1225 end
1205
1226
1206 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1227 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1207 issue = Issue.find(11)
1228 issue = Issue.find(11)
1208 assert_equal 'closed', issue.fixed_version.status
1229 assert_equal 'closed', issue.fixed_version.status
1209 issue.subject = 'Subject changed'
1230 issue.subject = 'Subject changed'
1210 assert issue.save
1231 assert issue.save
1211 end
1232 end
1212
1233
1213 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1234 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1214 issue = Issue.find(11)
1235 issue = Issue.find(11)
1215 issue.status_id = 1
1236 issue.status_id = 1
1216 assert !issue.save
1237 assert !issue.save
1217 assert_not_equal [], issue.errors[:base]
1238 assert_not_equal [], issue.errors[:base]
1218 end
1239 end
1219
1240
1220 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1241 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1221 issue = Issue.find(11)
1242 issue = Issue.find(11)
1222 issue.status_id = 1
1243 issue.status_id = 1
1223 issue.fixed_version_id = 3
1244 issue.fixed_version_id = 3
1224 assert issue.save
1245 assert issue.save
1225 end
1246 end
1226
1247
1227 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1248 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1228 issue = Issue.find(12)
1249 issue = Issue.find(12)
1229 assert_equal 'locked', issue.fixed_version.status
1250 assert_equal 'locked', issue.fixed_version.status
1230 issue.status_id = 1
1251 issue.status_id = 1
1231 assert issue.save
1252 assert issue.save
1232 end
1253 end
1233
1254
1234 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1255 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1235 issue = Issue.find(2)
1256 issue = Issue.find(2)
1236 assert_equal 2, issue.fixed_version_id
1257 assert_equal 2, issue.fixed_version_id
1237 issue.project_id = 3
1258 issue.project_id = 3
1238 assert_nil issue.fixed_version_id
1259 assert_nil issue.fixed_version_id
1239 issue.fixed_version_id = 2
1260 issue.fixed_version_id = 2
1240 assert !issue.save
1261 assert !issue.save
1241 assert_include 'Target version is not included in the list', issue.errors.full_messages
1262 assert_include 'Target version is not included in the list', issue.errors.full_messages
1242 end
1263 end
1243
1264
1244 def test_should_keep_shared_version_when_changing_project
1265 def test_should_keep_shared_version_when_changing_project
1245 Version.find(2).update_attribute :sharing, 'tree'
1266 Version.find(2).update_attribute :sharing, 'tree'
1246
1267
1247 issue = Issue.find(2)
1268 issue = Issue.find(2)
1248 assert_equal 2, issue.fixed_version_id
1269 assert_equal 2, issue.fixed_version_id
1249 issue.project_id = 3
1270 issue.project_id = 3
1250 assert_equal 2, issue.fixed_version_id
1271 assert_equal 2, issue.fixed_version_id
1251 assert issue.save
1272 assert issue.save
1252 end
1273 end
1253
1274
1254 def test_allowed_target_projects_should_include_projects_with_issue_tracking_enabled
1275 def test_allowed_target_projects_should_include_projects_with_issue_tracking_enabled
1255 assert_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1276 assert_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1256 end
1277 end
1257
1278
1258 def test_allowed_target_projects_should_not_include_projects_with_issue_tracking_disabled
1279 def test_allowed_target_projects_should_not_include_projects_with_issue_tracking_disabled
1259 Project.find(2).disable_module! :issue_tracking
1280 Project.find(2).disable_module! :issue_tracking
1260 assert_not_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1281 assert_not_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1261 end
1282 end
1262
1283
1263 def test_move_to_another_project_with_same_category
1284 def test_move_to_another_project_with_same_category
1264 issue = Issue.find(1)
1285 issue = Issue.find(1)
1265 issue.project = Project.find(2)
1286 issue.project = Project.find(2)
1266 assert issue.save
1287 assert issue.save
1267 issue.reload
1288 issue.reload
1268 assert_equal 2, issue.project_id
1289 assert_equal 2, issue.project_id
1269 # Category changes
1290 # Category changes
1270 assert_equal 4, issue.category_id
1291 assert_equal 4, issue.category_id
1271 # Make sure time entries were move to the target project
1292 # Make sure time entries were move to the target project
1272 assert_equal 2, issue.time_entries.first.project_id
1293 assert_equal 2, issue.time_entries.first.project_id
1273 end
1294 end
1274
1295
1275 def test_move_to_another_project_without_same_category
1296 def test_move_to_another_project_without_same_category
1276 issue = Issue.find(2)
1297 issue = Issue.find(2)
1277 issue.project = Project.find(2)
1298 issue.project = Project.find(2)
1278 assert issue.save
1299 assert issue.save
1279 issue.reload
1300 issue.reload
1280 assert_equal 2, issue.project_id
1301 assert_equal 2, issue.project_id
1281 # Category cleared
1302 # Category cleared
1282 assert_nil issue.category_id
1303 assert_nil issue.category_id
1283 end
1304 end
1284
1305
1285 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1306 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1286 issue = Issue.find(1)
1307 issue = Issue.find(1)
1287 issue.update_attribute(:fixed_version_id, 1)
1308 issue.update_attribute(:fixed_version_id, 1)
1288 issue.project = Project.find(2)
1309 issue.project = Project.find(2)
1289 assert issue.save
1310 assert issue.save
1290 issue.reload
1311 issue.reload
1291 assert_equal 2, issue.project_id
1312 assert_equal 2, issue.project_id
1292 # Cleared fixed_version
1313 # Cleared fixed_version
1293 assert_equal nil, issue.fixed_version
1314 assert_equal nil, issue.fixed_version
1294 end
1315 end
1295
1316
1296 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1317 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1297 issue = Issue.find(1)
1318 issue = Issue.find(1)
1298 issue.update_attribute(:fixed_version_id, 4)
1319 issue.update_attribute(:fixed_version_id, 4)
1299 issue.project = Project.find(5)
1320 issue.project = Project.find(5)
1300 assert issue.save
1321 assert issue.save
1301 issue.reload
1322 issue.reload
1302 assert_equal 5, issue.project_id
1323 assert_equal 5, issue.project_id
1303 # Keep fixed_version
1324 # Keep fixed_version
1304 assert_equal 4, issue.fixed_version_id
1325 assert_equal 4, issue.fixed_version_id
1305 end
1326 end
1306
1327
1307 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1328 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1308 issue = Issue.find(1)
1329 issue = Issue.find(1)
1309 issue.update_attribute(:fixed_version_id, 1)
1330 issue.update_attribute(:fixed_version_id, 1)
1310 issue.project = Project.find(5)
1331 issue.project = Project.find(5)
1311 assert issue.save
1332 assert issue.save
1312 issue.reload
1333 issue.reload
1313 assert_equal 5, issue.project_id
1334 assert_equal 5, issue.project_id
1314 # Cleared fixed_version
1335 # Cleared fixed_version
1315 assert_equal nil, issue.fixed_version
1336 assert_equal nil, issue.fixed_version
1316 end
1337 end
1317
1338
1318 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1339 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1319 issue = Issue.find(1)
1340 issue = Issue.find(1)
1320 issue.update_attribute(:fixed_version_id, 7)
1341 issue.update_attribute(:fixed_version_id, 7)
1321 issue.project = Project.find(2)
1342 issue.project = Project.find(2)
1322 assert issue.save
1343 assert issue.save
1323 issue.reload
1344 issue.reload
1324 assert_equal 2, issue.project_id
1345 assert_equal 2, issue.project_id
1325 # Keep fixed_version
1346 # Keep fixed_version
1326 assert_equal 7, issue.fixed_version_id
1347 assert_equal 7, issue.fixed_version_id
1327 end
1348 end
1328
1349
1329 def test_move_to_another_project_should_keep_parent_if_valid
1350 def test_move_to_another_project_should_keep_parent_if_valid
1330 issue = Issue.find(1)
1351 issue = Issue.find(1)
1331 issue.update_attribute(:parent_issue_id, 2)
1352 issue.update_attribute(:parent_issue_id, 2)
1332 issue.project = Project.find(3)
1353 issue.project = Project.find(3)
1333 assert issue.save
1354 assert issue.save
1334 issue.reload
1355 issue.reload
1335 assert_equal 2, issue.parent_id
1356 assert_equal 2, issue.parent_id
1336 end
1357 end
1337
1358
1338 def test_move_to_another_project_should_clear_parent_if_not_valid
1359 def test_move_to_another_project_should_clear_parent_if_not_valid
1339 issue = Issue.find(1)
1360 issue = Issue.find(1)
1340 issue.update_attribute(:parent_issue_id, 2)
1361 issue.update_attribute(:parent_issue_id, 2)
1341 issue.project = Project.find(2)
1362 issue.project = Project.find(2)
1342 assert issue.save
1363 assert issue.save
1343 issue.reload
1364 issue.reload
1344 assert_nil issue.parent_id
1365 assert_nil issue.parent_id
1345 end
1366 end
1346
1367
1347 def test_move_to_another_project_with_disabled_tracker
1368 def test_move_to_another_project_with_disabled_tracker
1348 issue = Issue.find(1)
1369 issue = Issue.find(1)
1349 target = Project.find(2)
1370 target = Project.find(2)
1350 target.tracker_ids = [3]
1371 target.tracker_ids = [3]
1351 target.save
1372 target.save
1352 issue.project = target
1373 issue.project = target
1353 assert issue.save
1374 assert issue.save
1354 issue.reload
1375 issue.reload
1355 assert_equal 2, issue.project_id
1376 assert_equal 2, issue.project_id
1356 assert_equal 3, issue.tracker_id
1377 assert_equal 3, issue.tracker_id
1357 end
1378 end
1358
1379
1359 def test_copy_to_the_same_project
1380 def test_copy_to_the_same_project
1360 issue = Issue.find(1)
1381 issue = Issue.find(1)
1361 copy = issue.copy
1382 copy = issue.copy
1362 assert_difference 'Issue.count' do
1383 assert_difference 'Issue.count' do
1363 copy.save!
1384 copy.save!
1364 end
1385 end
1365 assert_kind_of Issue, copy
1386 assert_kind_of Issue, copy
1366 assert_equal issue.project, copy.project
1387 assert_equal issue.project, copy.project
1367 assert_equal "125", copy.custom_value_for(2).value
1388 assert_equal "125", copy.custom_value_for(2).value
1368 end
1389 end
1369
1390
1370 def test_copy_to_another_project_and_tracker
1391 def test_copy_to_another_project_and_tracker
1371 issue = Issue.find(1)
1392 issue = Issue.find(1)
1372 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1393 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1373 assert_difference 'Issue.count' do
1394 assert_difference 'Issue.count' do
1374 copy.save!
1395 copy.save!
1375 end
1396 end
1376 copy.reload
1397 copy.reload
1377 assert_kind_of Issue, copy
1398 assert_kind_of Issue, copy
1378 assert_equal Project.find(3), copy.project
1399 assert_equal Project.find(3), copy.project
1379 assert_equal Tracker.find(2), copy.tracker
1400 assert_equal Tracker.find(2), copy.tracker
1380 # Custom field #2 is not associated with target tracker
1401 # Custom field #2 is not associated with target tracker
1381 assert_nil copy.custom_value_for(2)
1402 assert_nil copy.custom_value_for(2)
1382 end
1403 end
1383
1404
1384 test "#copy should not create a journal" do
1405 test "#copy should not create a journal" do
1385 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false)
1406 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false)
1386 copy.save!
1407 copy.save!
1387 assert_equal 0, copy.reload.journals.size
1408 assert_equal 0, copy.reload.journals.size
1388 end
1409 end
1389
1410
1390 test "#copy should allow assigned_to changes" do
1411 test "#copy should allow assigned_to changes" do
1391 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1412 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1392 assert_equal 3, copy.assigned_to_id
1413 assert_equal 3, copy.assigned_to_id
1393 end
1414 end
1394
1415
1395 test "#copy should allow status changes" do
1416 test "#copy should allow status changes" do
1396 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1417 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1397 assert_equal 2, copy.status_id
1418 assert_equal 2, copy.status_id
1398 end
1419 end
1399
1420
1400 test "#copy should allow start date changes" do
1421 test "#copy should allow start date changes" do
1401 date = Date.today
1422 date = Date.today
1402 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1423 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1403 assert_equal date, copy.start_date
1424 assert_equal date, copy.start_date
1404 end
1425 end
1405
1426
1406 test "#copy should allow due date changes" do
1427 test "#copy should allow due date changes" do
1407 date = Date.today
1428 date = Date.today
1408 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1429 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1409 assert_equal date, copy.due_date
1430 assert_equal date, copy.due_date
1410 end
1431 end
1411
1432
1412 test "#copy should set current user as author" do
1433 test "#copy should set current user as author" do
1413 User.current = User.find(9)
1434 User.current = User.find(9)
1414 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1435 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1415 assert_equal User.current, copy.author
1436 assert_equal User.current, copy.author
1416 end
1437 end
1417
1438
1418 test "#copy should create a journal with notes" do
1439 test "#copy should create a journal with notes" do
1419 date = Date.today
1440 date = Date.today
1420 notes = "Notes added when copying"
1441 notes = "Notes added when copying"
1421 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false)
1442 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false)
1422 copy.init_journal(User.current, notes)
1443 copy.init_journal(User.current, notes)
1423 copy.save!
1444 copy.save!
1424
1445
1425 assert_equal 1, copy.journals.size
1446 assert_equal 1, copy.journals.size
1426 journal = copy.journals.first
1447 journal = copy.journals.first
1427 assert_equal 0, journal.details.size
1448 assert_equal 0, journal.details.size
1428 assert_equal notes, journal.notes
1449 assert_equal notes, journal.notes
1429 end
1450 end
1430
1451
1431 def test_valid_parent_project
1452 def test_valid_parent_project
1432 issue = Issue.find(1)
1453 issue = Issue.find(1)
1433 issue_in_same_project = Issue.find(2)
1454 issue_in_same_project = Issue.find(2)
1434 issue_in_child_project = Issue.find(5)
1455 issue_in_child_project = Issue.find(5)
1435 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1456 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1436 issue_in_other_child_project = Issue.find(6)
1457 issue_in_other_child_project = Issue.find(6)
1437 issue_in_different_tree = Issue.find(4)
1458 issue_in_different_tree = Issue.find(4)
1438
1459
1439 with_settings :cross_project_subtasks => '' do
1460 with_settings :cross_project_subtasks => '' do
1440 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1461 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1441 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1462 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1442 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1463 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1443 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1464 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1444 end
1465 end
1445
1466
1446 with_settings :cross_project_subtasks => 'system' do
1467 with_settings :cross_project_subtasks => 'system' do
1447 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1468 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1448 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1469 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1449 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1470 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1450 end
1471 end
1451
1472
1452 with_settings :cross_project_subtasks => 'tree' do
1473 with_settings :cross_project_subtasks => 'tree' do
1453 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1474 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1454 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1475 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1455 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1476 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1456 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1477 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1457
1478
1458 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1479 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1459 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1480 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1460 end
1481 end
1461
1482
1462 with_settings :cross_project_subtasks => 'descendants' do
1483 with_settings :cross_project_subtasks => 'descendants' do
1463 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1484 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1464 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1485 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1465 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1486 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1466 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1487 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1467
1488
1468 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1489 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1469 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1490 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1470 end
1491 end
1471 end
1492 end
1472
1493
1473 def test_recipients_should_include_previous_assignee
1494 def test_recipients_should_include_previous_assignee
1474 user = User.find(3)
1495 user = User.find(3)
1475 user.members.update_all ["mail_notification = ?", false]
1496 user.members.update_all ["mail_notification = ?", false]
1476 user.update_attribute :mail_notification, 'only_assigned'
1497 user.update_attribute :mail_notification, 'only_assigned'
1477
1498
1478 issue = Issue.find(2)
1499 issue = Issue.find(2)
1479 issue.assigned_to = nil
1500 issue.assigned_to = nil
1480 assert_include user.mail, issue.recipients
1501 assert_include user.mail, issue.recipients
1481 issue.save!
1502 issue.save!
1482 assert !issue.recipients.include?(user.mail)
1503 assert !issue.recipients.include?(user.mail)
1483 end
1504 end
1484
1505
1485 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1506 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1486 issue = Issue.find(12)
1507 issue = Issue.find(12)
1487 assert issue.recipients.include?(issue.author.mail)
1508 assert issue.recipients.include?(issue.author.mail)
1488 # copy the issue to a private project
1509 # copy the issue to a private project
1489 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1510 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1490 # author is not a member of project anymore
1511 # author is not a member of project anymore
1491 assert !copy.recipients.include?(copy.author.mail)
1512 assert !copy.recipients.include?(copy.author.mail)
1492 end
1513 end
1493
1514
1494 def test_recipients_should_include_the_assigned_group_members
1515 def test_recipients_should_include_the_assigned_group_members
1495 group_member = User.generate!
1516 group_member = User.generate!
1496 group = Group.generate!
1517 group = Group.generate!
1497 group.users << group_member
1518 group.users << group_member
1498
1519
1499 issue = Issue.find(12)
1520 issue = Issue.find(12)
1500 issue.assigned_to = group
1521 issue.assigned_to = group
1501 assert issue.recipients.include?(group_member.mail)
1522 assert issue.recipients.include?(group_member.mail)
1502 end
1523 end
1503
1524
1504 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1525 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1505 user = User.find(3)
1526 user = User.find(3)
1506 issue = Issue.find(9)
1527 issue = Issue.find(9)
1507 Watcher.create!(:user => user, :watchable => issue)
1528 Watcher.create!(:user => user, :watchable => issue)
1508 assert issue.watched_by?(user)
1529 assert issue.watched_by?(user)
1509 assert !issue.watcher_recipients.include?(user.mail)
1530 assert !issue.watcher_recipients.include?(user.mail)
1510 end
1531 end
1511
1532
1512 def test_issue_destroy
1533 def test_issue_destroy
1513 Issue.find(1).destroy
1534 Issue.find(1).destroy
1514 assert_nil Issue.find_by_id(1)
1535 assert_nil Issue.find_by_id(1)
1515 assert_nil TimeEntry.find_by_issue_id(1)
1536 assert_nil TimeEntry.find_by_issue_id(1)
1516 end
1537 end
1517
1538
1518 def test_destroy_should_delete_time_entries_custom_values
1539 def test_destroy_should_delete_time_entries_custom_values
1519 issue = Issue.generate!
1540 issue = Issue.generate!
1520 time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'})
1541 time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'})
1521
1542
1522 assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do
1543 assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do
1523 assert issue.destroy
1544 assert issue.destroy
1524 end
1545 end
1525 end
1546 end
1526
1547
1527 def test_destroying_a_deleted_issue_should_not_raise_an_error
1548 def test_destroying_a_deleted_issue_should_not_raise_an_error
1528 issue = Issue.find(1)
1549 issue = Issue.find(1)
1529 Issue.find(1).destroy
1550 Issue.find(1).destroy
1530
1551
1531 assert_nothing_raised do
1552 assert_nothing_raised do
1532 assert_no_difference 'Issue.count' do
1553 assert_no_difference 'Issue.count' do
1533 issue.destroy
1554 issue.destroy
1534 end
1555 end
1535 assert issue.destroyed?
1556 assert issue.destroyed?
1536 end
1557 end
1537 end
1558 end
1538
1559
1539 def test_destroying_a_stale_issue_should_not_raise_an_error
1560 def test_destroying_a_stale_issue_should_not_raise_an_error
1540 issue = Issue.find(1)
1561 issue = Issue.find(1)
1541 Issue.find(1).update_attribute :subject, "Updated"
1562 Issue.find(1).update_attribute :subject, "Updated"
1542
1563
1543 assert_nothing_raised do
1564 assert_nothing_raised do
1544 assert_difference 'Issue.count', -1 do
1565 assert_difference 'Issue.count', -1 do
1545 issue.destroy
1566 issue.destroy
1546 end
1567 end
1547 assert issue.destroyed?
1568 assert issue.destroyed?
1548 end
1569 end
1549 end
1570 end
1550
1571
1551 def test_blocked
1572 def test_blocked
1552 blocked_issue = Issue.find(9)
1573 blocked_issue = Issue.find(9)
1553 blocking_issue = Issue.find(10)
1574 blocking_issue = Issue.find(10)
1554
1575
1555 assert blocked_issue.blocked?
1576 assert blocked_issue.blocked?
1556 assert !blocking_issue.blocked?
1577 assert !blocking_issue.blocked?
1557 end
1578 end
1558
1579
1559 def test_blocked_issues_dont_allow_closed_statuses
1580 def test_blocked_issues_dont_allow_closed_statuses
1560 blocked_issue = Issue.find(9)
1581 blocked_issue = Issue.find(9)
1561
1582
1562 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1583 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1563 assert !allowed_statuses.empty?
1584 assert !allowed_statuses.empty?
1564 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1585 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1565 assert closed_statuses.empty?
1586 assert closed_statuses.empty?
1566 end
1587 end
1567
1588
1568 def test_unblocked_issues_allow_closed_statuses
1589 def test_unblocked_issues_allow_closed_statuses
1569 blocking_issue = Issue.find(10)
1590 blocking_issue = Issue.find(10)
1570
1591
1571 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1592 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1572 assert !allowed_statuses.empty?
1593 assert !allowed_statuses.empty?
1573 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1594 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1574 assert !closed_statuses.empty?
1595 assert !closed_statuses.empty?
1575 end
1596 end
1576
1597
1577 def test_reschedule_an_issue_without_dates
1598 def test_reschedule_an_issue_without_dates
1578 with_settings :non_working_week_days => [] do
1599 with_settings :non_working_week_days => [] do
1579 issue = Issue.new(:start_date => nil, :due_date => nil)
1600 issue = Issue.new(:start_date => nil, :due_date => nil)
1580 issue.reschedule_on '2012-10-09'.to_date
1601 issue.reschedule_on '2012-10-09'.to_date
1581 assert_equal '2012-10-09'.to_date, issue.start_date
1602 assert_equal '2012-10-09'.to_date, issue.start_date
1582 assert_equal '2012-10-09'.to_date, issue.due_date
1603 assert_equal '2012-10-09'.to_date, issue.due_date
1583 end
1604 end
1584
1605
1585 with_settings :non_working_week_days => %w(6 7) do
1606 with_settings :non_working_week_days => %w(6 7) do
1586 issue = Issue.new(:start_date => nil, :due_date => nil)
1607 issue = Issue.new(:start_date => nil, :due_date => nil)
1587 issue.reschedule_on '2012-10-09'.to_date
1608 issue.reschedule_on '2012-10-09'.to_date
1588 assert_equal '2012-10-09'.to_date, issue.start_date
1609 assert_equal '2012-10-09'.to_date, issue.start_date
1589 assert_equal '2012-10-09'.to_date, issue.due_date
1610 assert_equal '2012-10-09'.to_date, issue.due_date
1590
1611
1591 issue = Issue.new(:start_date => nil, :due_date => nil)
1612 issue = Issue.new(:start_date => nil, :due_date => nil)
1592 issue.reschedule_on '2012-10-13'.to_date
1613 issue.reschedule_on '2012-10-13'.to_date
1593 assert_equal '2012-10-15'.to_date, issue.start_date
1614 assert_equal '2012-10-15'.to_date, issue.start_date
1594 assert_equal '2012-10-15'.to_date, issue.due_date
1615 assert_equal '2012-10-15'.to_date, issue.due_date
1595 end
1616 end
1596 end
1617 end
1597
1618
1598 def test_reschedule_an_issue_with_start_date
1619 def test_reschedule_an_issue_with_start_date
1599 with_settings :non_working_week_days => [] do
1620 with_settings :non_working_week_days => [] do
1600 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1621 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1601 issue.reschedule_on '2012-10-13'.to_date
1622 issue.reschedule_on '2012-10-13'.to_date
1602 assert_equal '2012-10-13'.to_date, issue.start_date
1623 assert_equal '2012-10-13'.to_date, issue.start_date
1603 assert_equal '2012-10-13'.to_date, issue.due_date
1624 assert_equal '2012-10-13'.to_date, issue.due_date
1604 end
1625 end
1605
1626
1606 with_settings :non_working_week_days => %w(6 7) do
1627 with_settings :non_working_week_days => %w(6 7) do
1607 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1628 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1608 issue.reschedule_on '2012-10-11'.to_date
1629 issue.reschedule_on '2012-10-11'.to_date
1609 assert_equal '2012-10-11'.to_date, issue.start_date
1630 assert_equal '2012-10-11'.to_date, issue.start_date
1610 assert_equal '2012-10-11'.to_date, issue.due_date
1631 assert_equal '2012-10-11'.to_date, issue.due_date
1611
1632
1612 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1633 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1613 issue.reschedule_on '2012-10-13'.to_date
1634 issue.reschedule_on '2012-10-13'.to_date
1614 assert_equal '2012-10-15'.to_date, issue.start_date
1635 assert_equal '2012-10-15'.to_date, issue.start_date
1615 assert_equal '2012-10-15'.to_date, issue.due_date
1636 assert_equal '2012-10-15'.to_date, issue.due_date
1616 end
1637 end
1617 end
1638 end
1618
1639
1619 def test_reschedule_an_issue_with_start_and_due_dates
1640 def test_reschedule_an_issue_with_start_and_due_dates
1620 with_settings :non_working_week_days => [] do
1641 with_settings :non_working_week_days => [] do
1621 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1642 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1622 issue.reschedule_on '2012-10-13'.to_date
1643 issue.reschedule_on '2012-10-13'.to_date
1623 assert_equal '2012-10-13'.to_date, issue.start_date
1644 assert_equal '2012-10-13'.to_date, issue.start_date
1624 assert_equal '2012-10-19'.to_date, issue.due_date
1645 assert_equal '2012-10-19'.to_date, issue.due_date
1625 end
1646 end
1626
1647
1627 with_settings :non_working_week_days => %w(6 7) do
1648 with_settings :non_working_week_days => %w(6 7) do
1628 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1649 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1629 issue.reschedule_on '2012-10-11'.to_date
1650 issue.reschedule_on '2012-10-11'.to_date
1630 assert_equal '2012-10-11'.to_date, issue.start_date
1651 assert_equal '2012-10-11'.to_date, issue.start_date
1631 assert_equal '2012-10-23'.to_date, issue.due_date
1652 assert_equal '2012-10-23'.to_date, issue.due_date
1632
1653
1633 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1654 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1634 issue.reschedule_on '2012-10-13'.to_date
1655 issue.reschedule_on '2012-10-13'.to_date
1635 assert_equal '2012-10-15'.to_date, issue.start_date
1656 assert_equal '2012-10-15'.to_date, issue.start_date
1636 assert_equal '2012-10-25'.to_date, issue.due_date
1657 assert_equal '2012-10-25'.to_date, issue.due_date
1637 end
1658 end
1638 end
1659 end
1639
1660
1640 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1661 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1641 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1662 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1642 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1663 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1643 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1664 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1644 :relation_type => IssueRelation::TYPE_PRECEDES)
1665 :relation_type => IssueRelation::TYPE_PRECEDES)
1645 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1666 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1646
1667
1647 issue1.reload
1668 issue1.reload
1648 issue1.due_date = '2012-10-23'
1669 issue1.due_date = '2012-10-23'
1649 issue1.save!
1670 issue1.save!
1650 issue2.reload
1671 issue2.reload
1651 assert_equal Date.parse('2012-10-24'), issue2.start_date
1672 assert_equal Date.parse('2012-10-24'), issue2.start_date
1652 assert_equal Date.parse('2012-10-26'), issue2.due_date
1673 assert_equal Date.parse('2012-10-26'), issue2.due_date
1653 end
1674 end
1654
1675
1655 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1676 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1656 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1677 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1657 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1678 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1658 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1679 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1659 :relation_type => IssueRelation::TYPE_PRECEDES)
1680 :relation_type => IssueRelation::TYPE_PRECEDES)
1660 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1681 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1661
1682
1662 issue1.reload
1683 issue1.reload
1663 issue1.start_date = '2012-09-17'
1684 issue1.start_date = '2012-09-17'
1664 issue1.due_date = '2012-09-18'
1685 issue1.due_date = '2012-09-18'
1665 issue1.save!
1686 issue1.save!
1666 issue2.reload
1687 issue2.reload
1667 assert_equal Date.parse('2012-09-19'), issue2.start_date
1688 assert_equal Date.parse('2012-09-19'), issue2.start_date
1668 assert_equal Date.parse('2012-09-21'), issue2.due_date
1689 assert_equal Date.parse('2012-09-21'), issue2.due_date
1669 end
1690 end
1670
1691
1671 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1692 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1672 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1693 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1673 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1694 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1674 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1695 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1675 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1696 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1676 :relation_type => IssueRelation::TYPE_PRECEDES)
1697 :relation_type => IssueRelation::TYPE_PRECEDES)
1677 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1698 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1678 :relation_type => IssueRelation::TYPE_PRECEDES)
1699 :relation_type => IssueRelation::TYPE_PRECEDES)
1679 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1700 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1680
1701
1681 issue1.reload
1702 issue1.reload
1682 issue1.start_date = '2012-09-17'
1703 issue1.start_date = '2012-09-17'
1683 issue1.due_date = '2012-09-18'
1704 issue1.due_date = '2012-09-18'
1684 issue1.save!
1705 issue1.save!
1685 issue2.reload
1706 issue2.reload
1686 # Issue 2 must start after Issue 3
1707 # Issue 2 must start after Issue 3
1687 assert_equal Date.parse('2012-10-03'), issue2.start_date
1708 assert_equal Date.parse('2012-10-03'), issue2.start_date
1688 assert_equal Date.parse('2012-10-05'), issue2.due_date
1709 assert_equal Date.parse('2012-10-05'), issue2.due_date
1689 end
1710 end
1690
1711
1691 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1712 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1692 with_settings :non_working_week_days => [] do
1713 with_settings :non_working_week_days => [] do
1693 stale = Issue.find(1)
1714 stale = Issue.find(1)
1694 issue = Issue.find(1)
1715 issue = Issue.find(1)
1695 issue.subject = "Updated"
1716 issue.subject = "Updated"
1696 issue.save!
1717 issue.save!
1697 date = 10.days.from_now.to_date
1718 date = 10.days.from_now.to_date
1698 assert_nothing_raised do
1719 assert_nothing_raised do
1699 stale.reschedule_on!(date)
1720 stale.reschedule_on!(date)
1700 end
1721 end
1701 assert_equal date, stale.reload.start_date
1722 assert_equal date, stale.reload.start_date
1702 end
1723 end
1703 end
1724 end
1704
1725
1705 def test_child_issue_should_consider_parent_soonest_start_on_create
1726 def test_child_issue_should_consider_parent_soonest_start_on_create
1706 set_language_if_valid 'en'
1727 set_language_if_valid 'en'
1707 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1728 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1708 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1729 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1709 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1730 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1710 :relation_type => IssueRelation::TYPE_PRECEDES)
1731 :relation_type => IssueRelation::TYPE_PRECEDES)
1711 issue1.reload
1732 issue1.reload
1712 issue2.reload
1733 issue2.reload
1713 assert_equal Date.parse('2012-10-18'), issue2.start_date
1734 assert_equal Date.parse('2012-10-18'), issue2.start_date
1714
1735
1715 with_settings :date_format => '%m/%d/%Y' do
1736 with_settings :date_format => '%m/%d/%Y' do
1716 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1737 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1717 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1738 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1718 assert !child.valid?
1739 assert !child.valid?
1719 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1740 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1720 assert_equal Date.parse('2012-10-18'), child.soonest_start
1741 assert_equal Date.parse('2012-10-18'), child.soonest_start
1721 child.start_date = '2012-10-18'
1742 child.start_date = '2012-10-18'
1722 assert child.save
1743 assert child.save
1723 end
1744 end
1724 end
1745 end
1725
1746
1726 def test_setting_parent_to_a_dependent_issue_should_not_validate
1747 def test_setting_parent_to_a_dependent_issue_should_not_validate
1727 set_language_if_valid 'en'
1748 set_language_if_valid 'en'
1728 issue1 = Issue.generate!
1749 issue1 = Issue.generate!
1729 issue2 = Issue.generate!
1750 issue2 = Issue.generate!
1730 issue3 = Issue.generate!
1751 issue3 = Issue.generate!
1731 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1752 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1732 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1753 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1733 issue3.reload
1754 issue3.reload
1734 issue3.parent_issue_id = issue2.id
1755 issue3.parent_issue_id = issue2.id
1735 assert !issue3.valid?
1756 assert !issue3.valid?
1736 assert_include 'Parent task is invalid', issue3.errors.full_messages
1757 assert_include 'Parent task is invalid', issue3.errors.full_messages
1737 end
1758 end
1738
1759
1739 def test_setting_parent_should_not_allow_circular_dependency
1760 def test_setting_parent_should_not_allow_circular_dependency
1740 set_language_if_valid 'en'
1761 set_language_if_valid 'en'
1741 issue1 = Issue.generate!
1762 issue1 = Issue.generate!
1742 issue2 = Issue.generate!
1763 issue2 = Issue.generate!
1743 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1764 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1744 issue3 = Issue.generate!
1765 issue3 = Issue.generate!
1745 issue2.reload
1766 issue2.reload
1746 issue2.parent_issue_id = issue3.id
1767 issue2.parent_issue_id = issue3.id
1747 issue2.save!
1768 issue2.save!
1748 issue4 = Issue.generate!
1769 issue4 = Issue.generate!
1749 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1770 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1750 issue4.reload
1771 issue4.reload
1751 issue4.parent_issue_id = issue1.id
1772 issue4.parent_issue_id = issue1.id
1752 assert !issue4.valid?
1773 assert !issue4.valid?
1753 assert_include 'Parent task is invalid', issue4.errors.full_messages
1774 assert_include 'Parent task is invalid', issue4.errors.full_messages
1754 end
1775 end
1755
1776
1756 def test_overdue
1777 def test_overdue
1757 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1778 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1758 assert !Issue.new(:due_date => Date.today).overdue?
1779 assert !Issue.new(:due_date => Date.today).overdue?
1759 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1780 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1760 assert !Issue.new(:due_date => nil).overdue?
1781 assert !Issue.new(:due_date => nil).overdue?
1761 assert !Issue.new(:due_date => 1.day.ago.to_date,
1782 assert !Issue.new(:due_date => 1.day.ago.to_date,
1762 :status => IssueStatus.where(:is_closed => true).first
1783 :status => IssueStatus.where(:is_closed => true).first
1763 ).overdue?
1784 ).overdue?
1764 end
1785 end
1765
1786
1766 test "#behind_schedule? should be false if the issue has no start_date" do
1787 test "#behind_schedule? should be false if the issue has no start_date" do
1767 assert !Issue.new(:start_date => nil,
1788 assert !Issue.new(:start_date => nil,
1768 :due_date => 1.day.from_now.to_date,
1789 :due_date => 1.day.from_now.to_date,
1769 :done_ratio => 0).behind_schedule?
1790 :done_ratio => 0).behind_schedule?
1770 end
1791 end
1771
1792
1772 test "#behind_schedule? should be false if the issue has no end_date" do
1793 test "#behind_schedule? should be false if the issue has no end_date" do
1773 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1794 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1774 :due_date => nil,
1795 :due_date => nil,
1775 :done_ratio => 0).behind_schedule?
1796 :done_ratio => 0).behind_schedule?
1776 end
1797 end
1777
1798
1778 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1799 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1779 assert !Issue.new(:start_date => 50.days.ago.to_date,
1800 assert !Issue.new(:start_date => 50.days.ago.to_date,
1780 :due_date => 50.days.from_now.to_date,
1801 :due_date => 50.days.from_now.to_date,
1781 :done_ratio => 90).behind_schedule?
1802 :done_ratio => 90).behind_schedule?
1782 end
1803 end
1783
1804
1784 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1805 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1785 assert Issue.new(:start_date => 1.day.ago.to_date,
1806 assert Issue.new(:start_date => 1.day.ago.to_date,
1786 :due_date => 1.day.from_now.to_date,
1807 :due_date => 1.day.from_now.to_date,
1787 :done_ratio => 0).behind_schedule?
1808 :done_ratio => 0).behind_schedule?
1788 end
1809 end
1789
1810
1790 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1811 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1791 assert Issue.new(:start_date => 100.days.ago.to_date,
1812 assert Issue.new(:start_date => 100.days.ago.to_date,
1792 :due_date => Date.today,
1813 :due_date => Date.today,
1793 :done_ratio => 90).behind_schedule?
1814 :done_ratio => 90).behind_schedule?
1794 end
1815 end
1795
1816
1796 test "#assignable_users should be Users" do
1817 test "#assignable_users should be Users" do
1797 assert_kind_of User, Issue.find(1).assignable_users.first
1818 assert_kind_of User, Issue.find(1).assignable_users.first
1798 end
1819 end
1799
1820
1800 test "#assignable_users should include the issue author" do
1821 test "#assignable_users should include the issue author" do
1801 non_project_member = User.generate!
1822 non_project_member = User.generate!
1802 issue = Issue.generate!(:author => non_project_member)
1823 issue = Issue.generate!(:author => non_project_member)
1803
1824
1804 assert issue.assignable_users.include?(non_project_member)
1825 assert issue.assignable_users.include?(non_project_member)
1805 end
1826 end
1806
1827
1807 test "#assignable_users should include the current assignee" do
1828 test "#assignable_users should include the current assignee" do
1808 user = User.generate!
1829 user = User.generate!
1809 issue = Issue.generate!(:assigned_to => user)
1830 issue = Issue.generate!(:assigned_to => user)
1810 user.lock!
1831 user.lock!
1811
1832
1812 assert Issue.find(issue.id).assignable_users.include?(user)
1833 assert Issue.find(issue.id).assignable_users.include?(user)
1813 end
1834 end
1814
1835
1815 test "#assignable_users should not show the issue author twice" do
1836 test "#assignable_users should not show the issue author twice" do
1816 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1837 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1817 assert_equal 2, assignable_user_ids.length
1838 assert_equal 2, assignable_user_ids.length
1818
1839
1819 assignable_user_ids.each do |user_id|
1840 assignable_user_ids.each do |user_id|
1820 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1841 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1821 "User #{user_id} appears more or less than once"
1842 "User #{user_id} appears more or less than once"
1822 end
1843 end
1823 end
1844 end
1824
1845
1825 test "#assignable_users with issue_group_assignment should include groups" do
1846 test "#assignable_users with issue_group_assignment should include groups" do
1826 issue = Issue.new(:project => Project.find(2))
1847 issue = Issue.new(:project => Project.find(2))
1827
1848
1828 with_settings :issue_group_assignment => '1' do
1849 with_settings :issue_group_assignment => '1' do
1829 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1850 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1830 assert issue.assignable_users.include?(Group.find(11))
1851 assert issue.assignable_users.include?(Group.find(11))
1831 end
1852 end
1832 end
1853 end
1833
1854
1834 test "#assignable_users without issue_group_assignment should not include groups" do
1855 test "#assignable_users without issue_group_assignment should not include groups" do
1835 issue = Issue.new(:project => Project.find(2))
1856 issue = Issue.new(:project => Project.find(2))
1836
1857
1837 with_settings :issue_group_assignment => '0' do
1858 with_settings :issue_group_assignment => '0' do
1838 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1859 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1839 assert !issue.assignable_users.include?(Group.find(11))
1860 assert !issue.assignable_users.include?(Group.find(11))
1840 end
1861 end
1841 end
1862 end
1842
1863
1843 def test_assignable_users_should_not_include_builtin_groups
1864 def test_assignable_users_should_not_include_builtin_groups
1844 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [1])
1865 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [1])
1845 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [1])
1866 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [1])
1846 issue = Issue.new(:project => Project.find(1))
1867 issue = Issue.new(:project => Project.find(1))
1847
1868
1848 with_settings :issue_group_assignment => '1' do
1869 with_settings :issue_group_assignment => '1' do
1849 assert_nil issue.assignable_users.detect {|u| u.is_a?(GroupBuiltin)}
1870 assert_nil issue.assignable_users.detect {|u| u.is_a?(GroupBuiltin)}
1850 end
1871 end
1851 end
1872 end
1852
1873
1853 def test_create_should_send_email_notification
1874 def test_create_should_send_email_notification
1854 ActionMailer::Base.deliveries.clear
1875 ActionMailer::Base.deliveries.clear
1855 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1876 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1856 :author_id => 3, :status_id => 1,
1877 :author_id => 3, :status_id => 1,
1857 :priority => IssuePriority.all.first,
1878 :priority => IssuePriority.all.first,
1858 :subject => 'test_create', :estimated_hours => '1:30')
1879 :subject => 'test_create', :estimated_hours => '1:30')
1859 with_settings :notified_events => %w(issue_added) do
1880 with_settings :notified_events => %w(issue_added) do
1860 assert issue.save
1881 assert issue.save
1861 assert_equal 1, ActionMailer::Base.deliveries.size
1882 assert_equal 1, ActionMailer::Base.deliveries.size
1862 end
1883 end
1863 end
1884 end
1864
1885
1865 def test_create_should_send_one_email_notification_with_both_settings
1886 def test_create_should_send_one_email_notification_with_both_settings
1866 ActionMailer::Base.deliveries.clear
1887 ActionMailer::Base.deliveries.clear
1867 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1888 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1868 :author_id => 3, :status_id => 1,
1889 :author_id => 3, :status_id => 1,
1869 :priority => IssuePriority.all.first,
1890 :priority => IssuePriority.all.first,
1870 :subject => 'test_create', :estimated_hours => '1:30')
1891 :subject => 'test_create', :estimated_hours => '1:30')
1871 with_settings :notified_events => %w(issue_added issue_updated) do
1892 with_settings :notified_events => %w(issue_added issue_updated) do
1872 assert issue.save
1893 assert issue.save
1873 assert_equal 1, ActionMailer::Base.deliveries.size
1894 assert_equal 1, ActionMailer::Base.deliveries.size
1874 end
1895 end
1875 end
1896 end
1876
1897
1877 def test_create_should_not_send_email_notification_with_no_setting
1898 def test_create_should_not_send_email_notification_with_no_setting
1878 ActionMailer::Base.deliveries.clear
1899 ActionMailer::Base.deliveries.clear
1879 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1900 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1880 :author_id => 3, :status_id => 1,
1901 :author_id => 3, :status_id => 1,
1881 :priority => IssuePriority.all.first,
1902 :priority => IssuePriority.all.first,
1882 :subject => 'test_create', :estimated_hours => '1:30')
1903 :subject => 'test_create', :estimated_hours => '1:30')
1883 with_settings :notified_events => [] do
1904 with_settings :notified_events => [] do
1884 assert issue.save
1905 assert issue.save
1885 assert_equal 0, ActionMailer::Base.deliveries.size
1906 assert_equal 0, ActionMailer::Base.deliveries.size
1886 end
1907 end
1887 end
1908 end
1888
1909
1889 def test_update_should_notify_previous_assignee
1910 def test_update_should_notify_previous_assignee
1890 ActionMailer::Base.deliveries.clear
1911 ActionMailer::Base.deliveries.clear
1891 user = User.find(3)
1912 user = User.find(3)
1892 user.members.update_all ["mail_notification = ?", false]
1913 user.members.update_all ["mail_notification = ?", false]
1893 user.update_attribute :mail_notification, 'only_assigned'
1914 user.update_attribute :mail_notification, 'only_assigned'
1894
1915
1895 with_settings :notified_events => %w(issue_updated) do
1916 with_settings :notified_events => %w(issue_updated) do
1896 issue = Issue.find(2)
1917 issue = Issue.find(2)
1897 issue.init_journal User.find(1)
1918 issue.init_journal User.find(1)
1898 issue.assigned_to = nil
1919 issue.assigned_to = nil
1899 issue.save!
1920 issue.save!
1900 assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
1921 assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
1901 end
1922 end
1902 end
1923 end
1903
1924
1904 def test_stale_issue_should_not_send_email_notification
1925 def test_stale_issue_should_not_send_email_notification
1905 ActionMailer::Base.deliveries.clear
1926 ActionMailer::Base.deliveries.clear
1906 issue = Issue.find(1)
1927 issue = Issue.find(1)
1907 stale = Issue.find(1)
1928 stale = Issue.find(1)
1908
1929
1909 issue.init_journal(User.find(1))
1930 issue.init_journal(User.find(1))
1910 issue.subject = 'Subjet update'
1931 issue.subject = 'Subjet update'
1911 with_settings :notified_events => %w(issue_updated) do
1932 with_settings :notified_events => %w(issue_updated) do
1912 assert issue.save
1933 assert issue.save
1913 assert_equal 1, ActionMailer::Base.deliveries.size
1934 assert_equal 1, ActionMailer::Base.deliveries.size
1914 ActionMailer::Base.deliveries.clear
1935 ActionMailer::Base.deliveries.clear
1915
1936
1916 stale.init_journal(User.find(1))
1937 stale.init_journal(User.find(1))
1917 stale.subject = 'Another subjet update'
1938 stale.subject = 'Another subjet update'
1918 assert_raise ActiveRecord::StaleObjectError do
1939 assert_raise ActiveRecord::StaleObjectError do
1919 stale.save
1940 stale.save
1920 end
1941 end
1921 assert ActionMailer::Base.deliveries.empty?
1942 assert ActionMailer::Base.deliveries.empty?
1922 end
1943 end
1923 end
1944 end
1924
1945
1925 def test_journalized_description
1946 def test_journalized_description
1926 IssueCustomField.delete_all
1947 IssueCustomField.delete_all
1927
1948
1928 i = Issue.first
1949 i = Issue.first
1929 old_description = i.description
1950 old_description = i.description
1930 new_description = "This is the new description"
1951 new_description = "This is the new description"
1931
1952
1932 i.init_journal(User.find(2))
1953 i.init_journal(User.find(2))
1933 i.description = new_description
1954 i.description = new_description
1934 assert_difference 'Journal.count', 1 do
1955 assert_difference 'Journal.count', 1 do
1935 assert_difference 'JournalDetail.count', 1 do
1956 assert_difference 'JournalDetail.count', 1 do
1936 i.save!
1957 i.save!
1937 end
1958 end
1938 end
1959 end
1939
1960
1940 detail = JournalDetail.order('id DESC').first
1961 detail = JournalDetail.order('id DESC').first
1941 assert_equal i, detail.journal.journalized
1962 assert_equal i, detail.journal.journalized
1942 assert_equal 'attr', detail.property
1963 assert_equal 'attr', detail.property
1943 assert_equal 'description', detail.prop_key
1964 assert_equal 'description', detail.prop_key
1944 assert_equal old_description, detail.old_value
1965 assert_equal old_description, detail.old_value
1945 assert_equal new_description, detail.value
1966 assert_equal new_description, detail.value
1946 end
1967 end
1947
1968
1948 def test_blank_descriptions_should_not_be_journalized
1969 def test_blank_descriptions_should_not_be_journalized
1949 IssueCustomField.delete_all
1970 IssueCustomField.delete_all
1950 Issue.where(:id => 1).update_all("description = NULL")
1971 Issue.where(:id => 1).update_all("description = NULL")
1951
1972
1952 i = Issue.find(1)
1973 i = Issue.find(1)
1953 i.init_journal(User.find(2))
1974 i.init_journal(User.find(2))
1954 i.subject = "blank description"
1975 i.subject = "blank description"
1955 i.description = "\r\n"
1976 i.description = "\r\n"
1956
1977
1957 assert_difference 'Journal.count', 1 do
1978 assert_difference 'Journal.count', 1 do
1958 assert_difference 'JournalDetail.count', 1 do
1979 assert_difference 'JournalDetail.count', 1 do
1959 i.save!
1980 i.save!
1960 end
1981 end
1961 end
1982 end
1962 end
1983 end
1963
1984
1964 def test_journalized_multi_custom_field
1985 def test_journalized_multi_custom_field
1965 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1986 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1966 :is_filter => true, :is_for_all => true,
1987 :is_filter => true, :is_for_all => true,
1967 :tracker_ids => [1],
1988 :tracker_ids => [1],
1968 :possible_values => ['value1', 'value2', 'value3'],
1989 :possible_values => ['value1', 'value2', 'value3'],
1969 :multiple => true)
1990 :multiple => true)
1970
1991
1971 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1992 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1972 :subject => 'Test', :author_id => 1)
1993 :subject => 'Test', :author_id => 1)
1973
1994
1974 assert_difference 'Journal.count' do
1995 assert_difference 'Journal.count' do
1975 assert_difference 'JournalDetail.count' do
1996 assert_difference 'JournalDetail.count' do
1976 issue.init_journal(User.first)
1997 issue.init_journal(User.first)
1977 issue.custom_field_values = {field.id => ['value1']}
1998 issue.custom_field_values = {field.id => ['value1']}
1978 issue.save!
1999 issue.save!
1979 end
2000 end
1980 assert_difference 'JournalDetail.count' do
2001 assert_difference 'JournalDetail.count' do
1981 issue.init_journal(User.first)
2002 issue.init_journal(User.first)
1982 issue.custom_field_values = {field.id => ['value1', 'value2']}
2003 issue.custom_field_values = {field.id => ['value1', 'value2']}
1983 issue.save!
2004 issue.save!
1984 end
2005 end
1985 assert_difference 'JournalDetail.count', 2 do
2006 assert_difference 'JournalDetail.count', 2 do
1986 issue.init_journal(User.first)
2007 issue.init_journal(User.first)
1987 issue.custom_field_values = {field.id => ['value3', 'value2']}
2008 issue.custom_field_values = {field.id => ['value3', 'value2']}
1988 issue.save!
2009 issue.save!
1989 end
2010 end
1990 assert_difference 'JournalDetail.count', 2 do
2011 assert_difference 'JournalDetail.count', 2 do
1991 issue.init_journal(User.first)
2012 issue.init_journal(User.first)
1992 issue.custom_field_values = {field.id => nil}
2013 issue.custom_field_values = {field.id => nil}
1993 issue.save!
2014 issue.save!
1994 end
2015 end
1995 end
2016 end
1996 end
2017 end
1997
2018
1998 def test_description_eol_should_be_normalized
2019 def test_description_eol_should_be_normalized
1999 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
2020 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
2000 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
2021 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
2001 end
2022 end
2002
2023
2003 def test_saving_twice_should_not_duplicate_journal_details
2024 def test_saving_twice_should_not_duplicate_journal_details
2004 i = Issue.first
2025 i = Issue.first
2005 i.init_journal(User.find(2), 'Some notes')
2026 i.init_journal(User.find(2), 'Some notes')
2006 # initial changes
2027 # initial changes
2007 i.subject = 'New subject'
2028 i.subject = 'New subject'
2008 i.done_ratio = i.done_ratio + 10
2029 i.done_ratio = i.done_ratio + 10
2009 assert_difference 'Journal.count' do
2030 assert_difference 'Journal.count' do
2010 assert i.save
2031 assert i.save
2011 end
2032 end
2012 # 1 more change
2033 # 1 more change
2013 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
2034 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
2014 assert_no_difference 'Journal.count' do
2035 assert_no_difference 'Journal.count' do
2015 assert_difference 'JournalDetail.count', 1 do
2036 assert_difference 'JournalDetail.count', 1 do
2016 i.save
2037 i.save
2017 end
2038 end
2018 end
2039 end
2019 # no more change
2040 # no more change
2020 assert_no_difference 'Journal.count' do
2041 assert_no_difference 'Journal.count' do
2021 assert_no_difference 'JournalDetail.count' do
2042 assert_no_difference 'JournalDetail.count' do
2022 i.save
2043 i.save
2023 end
2044 end
2024 end
2045 end
2025 end
2046 end
2026
2047
2027 def test_all_dependent_issues
2048 def test_all_dependent_issues
2028 IssueRelation.delete_all
2049 IssueRelation.delete_all
2029 assert IssueRelation.create!(:issue_from => Issue.find(1),
2050 assert IssueRelation.create!(:issue_from => Issue.find(1),
2030 :issue_to => Issue.find(2),
2051 :issue_to => Issue.find(2),
2031 :relation_type => IssueRelation::TYPE_PRECEDES)
2052 :relation_type => IssueRelation::TYPE_PRECEDES)
2032 assert IssueRelation.create!(:issue_from => Issue.find(2),
2053 assert IssueRelation.create!(:issue_from => Issue.find(2),
2033 :issue_to => Issue.find(3),
2054 :issue_to => Issue.find(3),
2034 :relation_type => IssueRelation::TYPE_PRECEDES)
2055 :relation_type => IssueRelation::TYPE_PRECEDES)
2035 assert IssueRelation.create!(:issue_from => Issue.find(3),
2056 assert IssueRelation.create!(:issue_from => Issue.find(3),
2036 :issue_to => Issue.find(8),
2057 :issue_to => Issue.find(8),
2037 :relation_type => IssueRelation::TYPE_PRECEDES)
2058 :relation_type => IssueRelation::TYPE_PRECEDES)
2038
2059
2039 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2060 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2040 end
2061 end
2041
2062
2042 def test_all_dependent_issues_with_subtask
2063 def test_all_dependent_issues_with_subtask
2043 IssueRelation.delete_all
2064 IssueRelation.delete_all
2044
2065
2045 project = Project.generate!(:name => "testproject")
2066 project = Project.generate!(:name => "testproject")
2046
2067
2047 parentIssue = Issue.generate!(:project => project)
2068 parentIssue = Issue.generate!(:project => project)
2048 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2069 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2049 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2070 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2050
2071
2051 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
2072 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
2052 end
2073 end
2053
2074
2054 def test_all_dependent_issues_does_not_include_self
2075 def test_all_dependent_issues_does_not_include_self
2055 IssueRelation.delete_all
2076 IssueRelation.delete_all
2056
2077
2057 project = Project.generate!(:name => "testproject")
2078 project = Project.generate!(:name => "testproject")
2058
2079
2059 parentIssue = Issue.generate!(:project => project)
2080 parentIssue = Issue.generate!(:project => project)
2060 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2081 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2061
2082
2062 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
2083 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
2063 end
2084 end
2064
2085
2065 def test_all_dependent_issues_with_parenttask_and_sibling
2086 def test_all_dependent_issues_with_parenttask_and_sibling
2066 IssueRelation.delete_all
2087 IssueRelation.delete_all
2067
2088
2068 project = Project.generate!(:name => "testproject")
2089 project = Project.generate!(:name => "testproject")
2069
2090
2070 parentIssue = Issue.generate!(:project => project)
2091 parentIssue = Issue.generate!(:project => project)
2071 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2092 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2072 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2093 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2073
2094
2074 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
2095 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
2075 end
2096 end
2076
2097
2077 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
2098 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
2078 IssueRelation.delete_all
2099 IssueRelation.delete_all
2079
2100
2080 project = Project.generate!(:name => "testproject")
2101 project = Project.generate!(:name => "testproject")
2081
2102
2082 parentIssue1 = Issue.generate!(:project => project)
2103 parentIssue1 = Issue.generate!(:project => project)
2083 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2104 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2084 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2105 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2085
2106
2086 parentIssue2 = Issue.generate!(:project => project)
2107 parentIssue2 = Issue.generate!(:project => project)
2087 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2108 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2088 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2109 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2089
2110
2090
2111
2091 assert IssueRelation.create(:issue_from => parentIssue1,
2112 assert IssueRelation.create(:issue_from => parentIssue1,
2092 :issue_to => childIssue2_2,
2113 :issue_to => childIssue2_2,
2093 :relation_type => IssueRelation::TYPE_BLOCKS)
2114 :relation_type => IssueRelation::TYPE_BLOCKS)
2094
2115
2095 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
2116 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
2096 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2117 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2097 end
2118 end
2098
2119
2099 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
2120 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
2100 IssueRelation.delete_all
2121 IssueRelation.delete_all
2101
2122
2102 project = Project.generate!(:name => "testproject")
2123 project = Project.generate!(:name => "testproject")
2103
2124
2104 parentIssue1 = Issue.generate!(:project => project)
2125 parentIssue1 = Issue.generate!(:project => project)
2105 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2126 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2106 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2127 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2107
2128
2108 parentIssue2 = Issue.generate!(:project => project)
2129 parentIssue2 = Issue.generate!(:project => project)
2109 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2130 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2110 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2131 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2111
2132
2112
2133
2113 assert IssueRelation.create(:issue_from => parentIssue1,
2134 assert IssueRelation.create(:issue_from => parentIssue1,
2114 :issue_to => parentIssue2,
2135 :issue_to => parentIssue2,
2115 :relation_type => IssueRelation::TYPE_BLOCKS)
2136 :relation_type => IssueRelation::TYPE_BLOCKS)
2116
2137
2117 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
2138 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
2118 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2139 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2119 end
2140 end
2120
2141
2121 def test_all_dependent_issues_with_transitive_relation
2142 def test_all_dependent_issues_with_transitive_relation
2122 IssueRelation.delete_all
2143 IssueRelation.delete_all
2123
2144
2124 project = Project.generate!(:name => "testproject")
2145 project = Project.generate!(:name => "testproject")
2125
2146
2126 parentIssue1 = Issue.generate!(:project => project)
2147 parentIssue1 = Issue.generate!(:project => project)
2127 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2148 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2128
2149
2129 parentIssue2 = Issue.generate!(:project => project)
2150 parentIssue2 = Issue.generate!(:project => project)
2130 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2151 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2131
2152
2132 independentIssue = Issue.generate!(:project => project)
2153 independentIssue = Issue.generate!(:project => project)
2133
2154
2134 assert IssueRelation.create(:issue_from => parentIssue1,
2155 assert IssueRelation.create(:issue_from => parentIssue1,
2135 :issue_to => childIssue2_1,
2156 :issue_to => childIssue2_1,
2136 :relation_type => IssueRelation::TYPE_RELATES)
2157 :relation_type => IssueRelation::TYPE_RELATES)
2137
2158
2138 assert IssueRelation.create(:issue_from => childIssue2_1,
2159 assert IssueRelation.create(:issue_from => childIssue2_1,
2139 :issue_to => independentIssue,
2160 :issue_to => independentIssue,
2140 :relation_type => IssueRelation::TYPE_RELATES)
2161 :relation_type => IssueRelation::TYPE_RELATES)
2141
2162
2142 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2163 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2143 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2164 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2144 end
2165 end
2145
2166
2146 def test_all_dependent_issues_with_transitive_relation2
2167 def test_all_dependent_issues_with_transitive_relation2
2147 IssueRelation.delete_all
2168 IssueRelation.delete_all
2148
2169
2149 project = Project.generate!(:name => "testproject")
2170 project = Project.generate!(:name => "testproject")
2150
2171
2151 parentIssue1 = Issue.generate!(:project => project)
2172 parentIssue1 = Issue.generate!(:project => project)
2152 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2173 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2153
2174
2154 parentIssue2 = Issue.generate!(:project => project)
2175 parentIssue2 = Issue.generate!(:project => project)
2155 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2176 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2156
2177
2157 independentIssue = Issue.generate!(:project => project)
2178 independentIssue = Issue.generate!(:project => project)
2158
2179
2159 assert IssueRelation.create(:issue_from => parentIssue1,
2180 assert IssueRelation.create(:issue_from => parentIssue1,
2160 :issue_to => independentIssue,
2181 :issue_to => independentIssue,
2161 :relation_type => IssueRelation::TYPE_RELATES)
2182 :relation_type => IssueRelation::TYPE_RELATES)
2162
2183
2163 assert IssueRelation.create(:issue_from => independentIssue,
2184 assert IssueRelation.create(:issue_from => independentIssue,
2164 :issue_to => childIssue2_1,
2185 :issue_to => childIssue2_1,
2165 :relation_type => IssueRelation::TYPE_RELATES)
2186 :relation_type => IssueRelation::TYPE_RELATES)
2166
2187
2167 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2188 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2168 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2189 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2169
2190
2170 end
2191 end
2171
2192
2172 def test_all_dependent_issues_with_persistent_circular_dependency
2193 def test_all_dependent_issues_with_persistent_circular_dependency
2173 IssueRelation.delete_all
2194 IssueRelation.delete_all
2174 assert IssueRelation.create!(:issue_from => Issue.find(1),
2195 assert IssueRelation.create!(:issue_from => Issue.find(1),
2175 :issue_to => Issue.find(2),
2196 :issue_to => Issue.find(2),
2176 :relation_type => IssueRelation::TYPE_PRECEDES)
2197 :relation_type => IssueRelation::TYPE_PRECEDES)
2177 assert IssueRelation.create!(:issue_from => Issue.find(2),
2198 assert IssueRelation.create!(:issue_from => Issue.find(2),
2178 :issue_to => Issue.find(3),
2199 :issue_to => Issue.find(3),
2179 :relation_type => IssueRelation::TYPE_PRECEDES)
2200 :relation_type => IssueRelation::TYPE_PRECEDES)
2180
2201
2181 r = IssueRelation.create!(:issue_from => Issue.find(3),
2202 r = IssueRelation.create!(:issue_from => Issue.find(3),
2182 :issue_to => Issue.find(7),
2203 :issue_to => Issue.find(7),
2183 :relation_type => IssueRelation::TYPE_PRECEDES)
2204 :relation_type => IssueRelation::TYPE_PRECEDES)
2184 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2205 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2185
2206
2186 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
2207 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
2187 end
2208 end
2188
2209
2189 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
2210 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
2190 IssueRelation.delete_all
2211 IssueRelation.delete_all
2191 assert IssueRelation.create!(:issue_from => Issue.find(1),
2212 assert IssueRelation.create!(:issue_from => Issue.find(1),
2192 :issue_to => Issue.find(2),
2213 :issue_to => Issue.find(2),
2193 :relation_type => IssueRelation::TYPE_RELATES)
2214 :relation_type => IssueRelation::TYPE_RELATES)
2194 assert IssueRelation.create!(:issue_from => Issue.find(2),
2215 assert IssueRelation.create!(:issue_from => Issue.find(2),
2195 :issue_to => Issue.find(3),
2216 :issue_to => Issue.find(3),
2196 :relation_type => IssueRelation::TYPE_RELATES)
2217 :relation_type => IssueRelation::TYPE_RELATES)
2197 assert IssueRelation.create!(:issue_from => Issue.find(3),
2218 assert IssueRelation.create!(:issue_from => Issue.find(3),
2198 :issue_to => Issue.find(8),
2219 :issue_to => Issue.find(8),
2199 :relation_type => IssueRelation::TYPE_RELATES)
2220 :relation_type => IssueRelation::TYPE_RELATES)
2200
2221
2201 r = IssueRelation.create!(:issue_from => Issue.find(8),
2222 r = IssueRelation.create!(:issue_from => Issue.find(8),
2202 :issue_to => Issue.find(7),
2223 :issue_to => Issue.find(7),
2203 :relation_type => IssueRelation::TYPE_RELATES)
2224 :relation_type => IssueRelation::TYPE_RELATES)
2204 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 2")
2225 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 2")
2205
2226
2206 r = IssueRelation.create!(:issue_from => Issue.find(3),
2227 r = IssueRelation.create!(:issue_from => Issue.find(3),
2207 :issue_to => Issue.find(7),
2228 :issue_to => Issue.find(7),
2208 :relation_type => IssueRelation::TYPE_RELATES)
2229 :relation_type => IssueRelation::TYPE_RELATES)
2209 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2230 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2210
2231
2211 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2232 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2212 end
2233 end
2213
2234
2214 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
2235 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
2215 @issue = Issue.find(1)
2236 @issue = Issue.find(1)
2216 @issue_status = IssueStatus.find(1)
2237 @issue_status = IssueStatus.find(1)
2217 @issue_status.update_attribute(:default_done_ratio, 50)
2238 @issue_status.update_attribute(:default_done_ratio, 50)
2218 @issue2 = Issue.find(2)
2239 @issue2 = Issue.find(2)
2219 @issue_status2 = IssueStatus.find(2)
2240 @issue_status2 = IssueStatus.find(2)
2220 @issue_status2.update_attribute(:default_done_ratio, 0)
2241 @issue_status2.update_attribute(:default_done_ratio, 0)
2221
2242
2222 with_settings :issue_done_ratio => 'issue_field' do
2243 with_settings :issue_done_ratio => 'issue_field' do
2223 assert_equal 0, @issue.done_ratio
2244 assert_equal 0, @issue.done_ratio
2224 assert_equal 30, @issue2.done_ratio
2245 assert_equal 30, @issue2.done_ratio
2225 end
2246 end
2226
2247
2227 with_settings :issue_done_ratio => 'issue_status' do
2248 with_settings :issue_done_ratio => 'issue_status' do
2228 assert_equal 50, @issue.done_ratio
2249 assert_equal 50, @issue.done_ratio
2229 assert_equal 0, @issue2.done_ratio
2250 assert_equal 0, @issue2.done_ratio
2230 end
2251 end
2231 end
2252 end
2232
2253
2233 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2254 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2234 @issue = Issue.find(1)
2255 @issue = Issue.find(1)
2235 @issue_status = IssueStatus.find(1)
2256 @issue_status = IssueStatus.find(1)
2236 @issue_status.update_attribute(:default_done_ratio, 50)
2257 @issue_status.update_attribute(:default_done_ratio, 50)
2237 @issue2 = Issue.find(2)
2258 @issue2 = Issue.find(2)
2238 @issue_status2 = IssueStatus.find(2)
2259 @issue_status2 = IssueStatus.find(2)
2239 @issue_status2.update_attribute(:default_done_ratio, 0)
2260 @issue_status2.update_attribute(:default_done_ratio, 0)
2240
2261
2241 with_settings :issue_done_ratio => 'issue_field' do
2262 with_settings :issue_done_ratio => 'issue_field' do
2242 @issue.update_done_ratio_from_issue_status
2263 @issue.update_done_ratio_from_issue_status
2243 @issue2.update_done_ratio_from_issue_status
2264 @issue2.update_done_ratio_from_issue_status
2244
2265
2245 assert_equal 0, @issue.read_attribute(:done_ratio)
2266 assert_equal 0, @issue.read_attribute(:done_ratio)
2246 assert_equal 30, @issue2.read_attribute(:done_ratio)
2267 assert_equal 30, @issue2.read_attribute(:done_ratio)
2247 end
2268 end
2248
2269
2249 with_settings :issue_done_ratio => 'issue_status' do
2270 with_settings :issue_done_ratio => 'issue_status' do
2250 @issue.update_done_ratio_from_issue_status
2271 @issue.update_done_ratio_from_issue_status
2251 @issue2.update_done_ratio_from_issue_status
2272 @issue2.update_done_ratio_from_issue_status
2252
2273
2253 assert_equal 50, @issue.read_attribute(:done_ratio)
2274 assert_equal 50, @issue.read_attribute(:done_ratio)
2254 assert_equal 0, @issue2.read_attribute(:done_ratio)
2275 assert_equal 0, @issue2.read_attribute(:done_ratio)
2255 end
2276 end
2256 end
2277 end
2257
2278
2258 test "#by_tracker" do
2279 test "#by_tracker" do
2259 User.current = User.anonymous
2280 User.current = User.anonymous
2260 groups = Issue.by_tracker(Project.find(1))
2281 groups = Issue.by_tracker(Project.find(1))
2261 assert_equal 3, groups.count
2282 assert_equal 3, groups.count
2262 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2283 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2263 end
2284 end
2264
2285
2265 test "#by_version" do
2286 test "#by_version" do
2266 User.current = User.anonymous
2287 User.current = User.anonymous
2267 groups = Issue.by_version(Project.find(1))
2288 groups = Issue.by_version(Project.find(1))
2268 assert_equal 3, groups.count
2289 assert_equal 3, groups.count
2269 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2290 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2270 end
2291 end
2271
2292
2272 test "#by_priority" do
2293 test "#by_priority" do
2273 User.current = User.anonymous
2294 User.current = User.anonymous
2274 groups = Issue.by_priority(Project.find(1))
2295 groups = Issue.by_priority(Project.find(1))
2275 assert_equal 4, groups.count
2296 assert_equal 4, groups.count
2276 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2297 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2277 end
2298 end
2278
2299
2279 test "#by_category" do
2300 test "#by_category" do
2280 User.current = User.anonymous
2301 User.current = User.anonymous
2281 groups = Issue.by_category(Project.find(1))
2302 groups = Issue.by_category(Project.find(1))
2282 assert_equal 2, groups.count
2303 assert_equal 2, groups.count
2283 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2304 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2284 end
2305 end
2285
2306
2286 test "#by_assigned_to" do
2307 test "#by_assigned_to" do
2287 User.current = User.anonymous
2308 User.current = User.anonymous
2288 groups = Issue.by_assigned_to(Project.find(1))
2309 groups = Issue.by_assigned_to(Project.find(1))
2289 assert_equal 2, groups.count
2310 assert_equal 2, groups.count
2290 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2311 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2291 end
2312 end
2292
2313
2293 test "#by_author" do
2314 test "#by_author" do
2294 User.current = User.anonymous
2315 User.current = User.anonymous
2295 groups = Issue.by_author(Project.find(1))
2316 groups = Issue.by_author(Project.find(1))
2296 assert_equal 4, groups.count
2317 assert_equal 4, groups.count
2297 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2318 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2298 end
2319 end
2299
2320
2300 test "#by_subproject" do
2321 test "#by_subproject" do
2301 User.current = User.anonymous
2322 User.current = User.anonymous
2302 groups = Issue.by_subproject(Project.find(1))
2323 groups = Issue.by_subproject(Project.find(1))
2303 # Private descendant not visible
2324 # Private descendant not visible
2304 assert_equal 1, groups.count
2325 assert_equal 1, groups.count
2305 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2326 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2306 end
2327 end
2307
2328
2308 def test_recently_updated_scope
2329 def test_recently_updated_scope
2309 #should return the last updated issue
2330 #should return the last updated issue
2310 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2331 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2311 end
2332 end
2312
2333
2313 def test_on_active_projects_scope
2334 def test_on_active_projects_scope
2314 assert Project.find(2).archive
2335 assert Project.find(2).archive
2315
2336
2316 before = Issue.on_active_project.length
2337 before = Issue.on_active_project.length
2317 # test inclusion to results
2338 # test inclusion to results
2318 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2339 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2319 assert_equal before + 1, Issue.on_active_project.length
2340 assert_equal before + 1, Issue.on_active_project.length
2320
2341
2321 # Move to an archived project
2342 # Move to an archived project
2322 issue.project = Project.find(2)
2343 issue.project = Project.find(2)
2323 assert issue.save
2344 assert issue.save
2324 assert_equal before, Issue.on_active_project.length
2345 assert_equal before, Issue.on_active_project.length
2325 end
2346 end
2326
2347
2327 test "Issue#recipients should include project recipients" do
2348 test "Issue#recipients should include project recipients" do
2328 issue = Issue.generate!
2349 issue = Issue.generate!
2329 assert issue.project.recipients.present?
2350 assert issue.project.recipients.present?
2330 issue.project.recipients.each do |project_recipient|
2351 issue.project.recipients.each do |project_recipient|
2331 assert issue.recipients.include?(project_recipient)
2352 assert issue.recipients.include?(project_recipient)
2332 end
2353 end
2333 end
2354 end
2334
2355
2335 test "Issue#recipients should include the author if the author is active" do
2356 test "Issue#recipients should include the author if the author is active" do
2336 issue = Issue.generate!(:author => User.generate!)
2357 issue = Issue.generate!(:author => User.generate!)
2337 assert issue.author, "No author set for Issue"
2358 assert issue.author, "No author set for Issue"
2338 assert issue.recipients.include?(issue.author.mail)
2359 assert issue.recipients.include?(issue.author.mail)
2339 end
2360 end
2340
2361
2341 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2362 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2342 issue = Issue.generate!(:assigned_to => User.generate!)
2363 issue = Issue.generate!(:assigned_to => User.generate!)
2343 assert issue.assigned_to, "No assigned_to set for Issue"
2364 assert issue.assigned_to, "No assigned_to set for Issue"
2344 assert issue.recipients.include?(issue.assigned_to.mail)
2365 assert issue.recipients.include?(issue.assigned_to.mail)
2345 end
2366 end
2346
2367
2347 test "Issue#recipients should not include users who opt out of all email" do
2368 test "Issue#recipients should not include users who opt out of all email" do
2348 issue = Issue.generate!(:author => User.generate!)
2369 issue = Issue.generate!(:author => User.generate!)
2349 issue.author.update_attribute(:mail_notification, :none)
2370 issue.author.update_attribute(:mail_notification, :none)
2350 assert !issue.recipients.include?(issue.author.mail)
2371 assert !issue.recipients.include?(issue.author.mail)
2351 end
2372 end
2352
2373
2353 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2374 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2354 issue = Issue.generate!(:author => User.generate!)
2375 issue = Issue.generate!(:author => User.generate!)
2355 issue.author.update_attribute(:mail_notification, :only_assigned)
2376 issue.author.update_attribute(:mail_notification, :only_assigned)
2356 assert !issue.recipients.include?(issue.author.mail)
2377 assert !issue.recipients.include?(issue.author.mail)
2357 end
2378 end
2358
2379
2359 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2380 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2360 issue = Issue.generate!(:assigned_to => User.generate!)
2381 issue = Issue.generate!(:assigned_to => User.generate!)
2361 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2382 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2362 assert !issue.recipients.include?(issue.assigned_to.mail)
2383 assert !issue.recipients.include?(issue.assigned_to.mail)
2363 end
2384 end
2364
2385
2365 def test_last_journal_id_with_journals_should_return_the_journal_id
2386 def test_last_journal_id_with_journals_should_return_the_journal_id
2366 assert_equal 2, Issue.find(1).last_journal_id
2387 assert_equal 2, Issue.find(1).last_journal_id
2367 end
2388 end
2368
2389
2369 def test_last_journal_id_without_journals_should_return_nil
2390 def test_last_journal_id_without_journals_should_return_nil
2370 assert_nil Issue.find(3).last_journal_id
2391 assert_nil Issue.find(3).last_journal_id
2371 end
2392 end
2372
2393
2373 def test_journals_after_should_return_journals_with_greater_id
2394 def test_journals_after_should_return_journals_with_greater_id
2374 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2395 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2375 assert_equal [], Issue.find(1).journals_after('2')
2396 assert_equal [], Issue.find(1).journals_after('2')
2376 end
2397 end
2377
2398
2378 def test_journals_after_with_blank_arg_should_return_all_journals
2399 def test_journals_after_with_blank_arg_should_return_all_journals
2379 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2400 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2380 end
2401 end
2381
2402
2382 def test_css_classes_should_include_tracker
2403 def test_css_classes_should_include_tracker
2383 issue = Issue.new(:tracker => Tracker.find(2))
2404 issue = Issue.new(:tracker => Tracker.find(2))
2384 classes = issue.css_classes.split(' ')
2405 classes = issue.css_classes.split(' ')
2385 assert_include 'tracker-2', classes
2406 assert_include 'tracker-2', classes
2386 end
2407 end
2387
2408
2388 def test_css_classes_should_include_priority
2409 def test_css_classes_should_include_priority
2389 issue = Issue.new(:priority => IssuePriority.find(8))
2410 issue = Issue.new(:priority => IssuePriority.find(8))
2390 classes = issue.css_classes.split(' ')
2411 classes = issue.css_classes.split(' ')
2391 assert_include 'priority-8', classes
2412 assert_include 'priority-8', classes
2392 assert_include 'priority-highest', classes
2413 assert_include 'priority-highest', classes
2393 end
2414 end
2394
2415
2395 def test_css_classes_should_include_user_and_group_assignment
2416 def test_css_classes_should_include_user_and_group_assignment
2396 project = Project.first
2417 project = Project.first
2397 user = User.generate!
2418 user = User.generate!
2398 group = Group.generate!
2419 group = Group.generate!
2399 Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
2420 Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
2400 group.users << user
2421 group.users << user
2401 assert user.member_of?(project)
2422 assert user.member_of?(project)
2402 issue1 = Issue.generate(:assigned_to_id => group.id)
2423 issue1 = Issue.generate(:assigned_to_id => group.id)
2403 assert_include 'assigned-to-my-group', issue1.css_classes(user)
2424 assert_include 'assigned-to-my-group', issue1.css_classes(user)
2404 assert_not_include 'assigned-to-me', issue1.css_classes(user)
2425 assert_not_include 'assigned-to-me', issue1.css_classes(user)
2405 issue2 = Issue.generate(:assigned_to_id => user.id)
2426 issue2 = Issue.generate(:assigned_to_id => user.id)
2406 assert_not_include 'assigned-to-my-group', issue2.css_classes(user)
2427 assert_not_include 'assigned-to-my-group', issue2.css_classes(user)
2407 assert_include 'assigned-to-me', issue2.css_classes(user)
2428 assert_include 'assigned-to-me', issue2.css_classes(user)
2408 end
2429 end
2409
2430
2410 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2431 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2411 set_tmp_attachments_directory
2432 set_tmp_attachments_directory
2412 issue = Issue.generate!
2433 issue = Issue.generate!
2413 issue.save_attachments({
2434 issue.save_attachments({
2414 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2435 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2415 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2436 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2416 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2437 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2417 })
2438 })
2418 issue.attach_saved_attachments
2439 issue.attach_saved_attachments
2419
2440
2420 assert_equal 3, issue.reload.attachments.count
2441 assert_equal 3, issue.reload.attachments.count
2421 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2442 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2422 end
2443 end
2423
2444
2424 def test_closed_on_should_be_nil_when_creating_an_open_issue
2445 def test_closed_on_should_be_nil_when_creating_an_open_issue
2425 issue = Issue.generate!(:status_id => 1).reload
2446 issue = Issue.generate!(:status_id => 1).reload
2426 assert !issue.closed?
2447 assert !issue.closed?
2427 assert_nil issue.closed_on
2448 assert_nil issue.closed_on
2428 end
2449 end
2429
2450
2430 def test_closed_on_should_be_set_when_creating_a_closed_issue
2451 def test_closed_on_should_be_set_when_creating_a_closed_issue
2431 issue = Issue.generate!(:status_id => 5).reload
2452 issue = Issue.generate!(:status_id => 5).reload
2432 assert issue.closed?
2453 assert issue.closed?
2433 assert_not_nil issue.closed_on
2454 assert_not_nil issue.closed_on
2434 assert_equal issue.updated_on, issue.closed_on
2455 assert_equal issue.updated_on, issue.closed_on
2435 assert_equal issue.created_on, issue.closed_on
2456 assert_equal issue.created_on, issue.closed_on
2436 end
2457 end
2437
2458
2438 def test_closed_on_should_be_nil_when_updating_an_open_issue
2459 def test_closed_on_should_be_nil_when_updating_an_open_issue
2439 issue = Issue.find(1)
2460 issue = Issue.find(1)
2440 issue.subject = 'Not closed yet'
2461 issue.subject = 'Not closed yet'
2441 issue.save!
2462 issue.save!
2442 issue.reload
2463 issue.reload
2443 assert_nil issue.closed_on
2464 assert_nil issue.closed_on
2444 end
2465 end
2445
2466
2446 def test_closed_on_should_be_set_when_closing_an_open_issue
2467 def test_closed_on_should_be_set_when_closing_an_open_issue
2447 issue = Issue.find(1)
2468 issue = Issue.find(1)
2448 issue.subject = 'Now closed'
2469 issue.subject = 'Now closed'
2449 issue.status_id = 5
2470 issue.status_id = 5
2450 issue.save!
2471 issue.save!
2451 issue.reload
2472 issue.reload
2452 assert_not_nil issue.closed_on
2473 assert_not_nil issue.closed_on
2453 assert_equal issue.updated_on, issue.closed_on
2474 assert_equal issue.updated_on, issue.closed_on
2454 end
2475 end
2455
2476
2456 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2477 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2457 issue = Issue.open(false).first
2478 issue = Issue.open(false).first
2458 was_closed_on = issue.closed_on
2479 was_closed_on = issue.closed_on
2459 assert_not_nil was_closed_on
2480 assert_not_nil was_closed_on
2460 issue.subject = 'Updating a closed issue'
2481 issue.subject = 'Updating a closed issue'
2461 issue.save!
2482 issue.save!
2462 issue.reload
2483 issue.reload
2463 assert_equal was_closed_on, issue.closed_on
2484 assert_equal was_closed_on, issue.closed_on
2464 end
2485 end
2465
2486
2466 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2487 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2467 issue = Issue.open(false).first
2488 issue = Issue.open(false).first
2468 was_closed_on = issue.closed_on
2489 was_closed_on = issue.closed_on
2469 assert_not_nil was_closed_on
2490 assert_not_nil was_closed_on
2470 issue.subject = 'Reopening a closed issue'
2491 issue.subject = 'Reopening a closed issue'
2471 issue.status_id = 1
2492 issue.status_id = 1
2472 issue.save!
2493 issue.save!
2473 issue.reload
2494 issue.reload
2474 assert !issue.closed?
2495 assert !issue.closed?
2475 assert_equal was_closed_on, issue.closed_on
2496 assert_equal was_closed_on, issue.closed_on
2476 end
2497 end
2477
2498
2478 def test_status_was_should_return_nil_for_new_issue
2499 def test_status_was_should_return_nil_for_new_issue
2479 issue = Issue.new
2500 issue = Issue.new
2480 assert_nil issue.status_was
2501 assert_nil issue.status_was
2481 end
2502 end
2482
2503
2483 def test_status_was_should_return_status_before_change
2504 def test_status_was_should_return_status_before_change
2484 issue = Issue.find(1)
2505 issue = Issue.find(1)
2485 issue.status = IssueStatus.find(2)
2506 issue.status = IssueStatus.find(2)
2486 assert_equal IssueStatus.find(1), issue.status_was
2507 assert_equal IssueStatus.find(1), issue.status_was
2487 end
2508 end
2488
2509
2489 def test_status_was_should_return_status_before_change_with_status_id
2510 def test_status_was_should_return_status_before_change_with_status_id
2490 issue = Issue.find(1)
2511 issue = Issue.find(1)
2491 assert_equal IssueStatus.find(1), issue.status
2512 assert_equal IssueStatus.find(1), issue.status
2492 issue.status_id = 2
2513 issue.status_id = 2
2493 assert_equal IssueStatus.find(1), issue.status_was
2514 assert_equal IssueStatus.find(1), issue.status_was
2494 end
2515 end
2495
2516
2496 def test_status_was_should_be_reset_on_save
2517 def test_status_was_should_be_reset_on_save
2497 issue = Issue.find(1)
2518 issue = Issue.find(1)
2498 issue.status = IssueStatus.find(2)
2519 issue.status = IssueStatus.find(2)
2499 assert_equal IssueStatus.find(1), issue.status_was
2520 assert_equal IssueStatus.find(1), issue.status_was
2500 assert issue.save!
2521 assert issue.save!
2501 assert_equal IssueStatus.find(2), issue.status_was
2522 assert_equal IssueStatus.find(2), issue.status_was
2502 end
2523 end
2503
2524
2504 def test_closing_should_return_true_when_closing_an_issue
2525 def test_closing_should_return_true_when_closing_an_issue
2505 issue = Issue.find(1)
2526 issue = Issue.find(1)
2506 issue.status = IssueStatus.find(2)
2527 issue.status = IssueStatus.find(2)
2507 assert_equal false, issue.closing?
2528 assert_equal false, issue.closing?
2508 issue.status = IssueStatus.find(5)
2529 issue.status = IssueStatus.find(5)
2509 assert_equal true, issue.closing?
2530 assert_equal true, issue.closing?
2510 end
2531 end
2511
2532
2512 def test_closing_should_return_true_when_closing_an_issue_with_status_id
2533 def test_closing_should_return_true_when_closing_an_issue_with_status_id
2513 issue = Issue.find(1)
2534 issue = Issue.find(1)
2514 issue.status_id = 2
2535 issue.status_id = 2
2515 assert_equal false, issue.closing?
2536 assert_equal false, issue.closing?
2516 issue.status_id = 5
2537 issue.status_id = 5
2517 assert_equal true, issue.closing?
2538 assert_equal true, issue.closing?
2518 end
2539 end
2519
2540
2520 def test_closing_should_return_true_for_new_closed_issue
2541 def test_closing_should_return_true_for_new_closed_issue
2521 issue = Issue.new
2542 issue = Issue.new
2522 assert_equal false, issue.closing?
2543 assert_equal false, issue.closing?
2523 issue.status = IssueStatus.find(5)
2544 issue.status = IssueStatus.find(5)
2524 assert_equal true, issue.closing?
2545 assert_equal true, issue.closing?
2525 end
2546 end
2526
2547
2527 def test_closing_should_return_true_for_new_closed_issue_with_status_id
2548 def test_closing_should_return_true_for_new_closed_issue_with_status_id
2528 issue = Issue.new
2549 issue = Issue.new
2529 assert_equal false, issue.closing?
2550 assert_equal false, issue.closing?
2530 issue.status_id = 5
2551 issue.status_id = 5
2531 assert_equal true, issue.closing?
2552 assert_equal true, issue.closing?
2532 end
2553 end
2533
2554
2534 def test_closing_should_be_reset_after_save
2555 def test_closing_should_be_reset_after_save
2535 issue = Issue.find(1)
2556 issue = Issue.find(1)
2536 issue.status_id = 5
2557 issue.status_id = 5
2537 assert_equal true, issue.closing?
2558 assert_equal true, issue.closing?
2538 issue.save!
2559 issue.save!
2539 assert_equal false, issue.closing?
2560 assert_equal false, issue.closing?
2540 end
2561 end
2541
2562
2542 def test_reopening_should_return_true_when_reopening_an_issue
2563 def test_reopening_should_return_true_when_reopening_an_issue
2543 issue = Issue.find(8)
2564 issue = Issue.find(8)
2544 issue.status = IssueStatus.find(6)
2565 issue.status = IssueStatus.find(6)
2545 assert_equal false, issue.reopening?
2566 assert_equal false, issue.reopening?
2546 issue.status = IssueStatus.find(2)
2567 issue.status = IssueStatus.find(2)
2547 assert_equal true, issue.reopening?
2568 assert_equal true, issue.reopening?
2548 end
2569 end
2549
2570
2550 def test_reopening_should_return_true_when_reopening_an_issue_with_status_id
2571 def test_reopening_should_return_true_when_reopening_an_issue_with_status_id
2551 issue = Issue.find(8)
2572 issue = Issue.find(8)
2552 issue.status_id = 6
2573 issue.status_id = 6
2553 assert_equal false, issue.reopening?
2574 assert_equal false, issue.reopening?
2554 issue.status_id = 2
2575 issue.status_id = 2
2555 assert_equal true, issue.reopening?
2576 assert_equal true, issue.reopening?
2556 end
2577 end
2557
2578
2558 def test_reopening_should_return_false_for_new_open_issue
2579 def test_reopening_should_return_false_for_new_open_issue
2559 issue = Issue.new
2580 issue = Issue.new
2560 issue.status = IssueStatus.find(1)
2581 issue.status = IssueStatus.find(1)
2561 assert_equal false, issue.reopening?
2582 assert_equal false, issue.reopening?
2562 end
2583 end
2563
2584
2564 def test_reopening_should_be_reset_after_save
2585 def test_reopening_should_be_reset_after_save
2565 issue = Issue.find(8)
2586 issue = Issue.find(8)
2566 issue.status_id = 2
2587 issue.status_id = 2
2567 assert_equal true, issue.reopening?
2588 assert_equal true, issue.reopening?
2568 issue.save!
2589 issue.save!
2569 assert_equal false, issue.reopening?
2590 assert_equal false, issue.reopening?
2570 end
2591 end
2571
2592
2572 def test_default_status_without_tracker_should_be_nil
2593 def test_default_status_without_tracker_should_be_nil
2573 issue = Issue.new
2594 issue = Issue.new
2574 assert_nil issue.tracker
2595 assert_nil issue.tracker
2575 assert_nil issue.default_status
2596 assert_nil issue.default_status
2576 end
2597 end
2577
2598
2578 def test_default_status_should_be_tracker_default_status
2599 def test_default_status_should_be_tracker_default_status
2579 issue = Issue.new(:tracker_id => 1)
2600 issue = Issue.new(:tracker_id => 1)
2580 assert_not_nil issue.status
2601 assert_not_nil issue.status
2581 assert_equal issue.tracker.default_status, issue.default_status
2602 assert_equal issue.tracker.default_status, issue.default_status
2582 end
2603 end
2583
2604
2584 def test_initializing_with_tracker_should_set_default_status
2605 def test_initializing_with_tracker_should_set_default_status
2585 issue = Issue.new(:tracker => Tracker.find(1))
2606 issue = Issue.new(:tracker => Tracker.find(1))
2586 assert_not_nil issue.status
2607 assert_not_nil issue.status
2587 assert_equal issue.default_status, issue.status
2608 assert_equal issue.default_status, issue.status
2588 end
2609 end
2589
2610
2590 def test_initializing_with_tracker_id_should_set_default_status
2611 def test_initializing_with_tracker_id_should_set_default_status
2591 issue = Issue.new(:tracker_id => 1)
2612 issue = Issue.new(:tracker_id => 1)
2592 assert_not_nil issue.status
2613 assert_not_nil issue.status
2593 assert_equal issue.default_status, issue.status
2614 assert_equal issue.default_status, issue.status
2594 end
2615 end
2595
2616
2596 def test_setting_tracker_should_set_default_status
2617 def test_setting_tracker_should_set_default_status
2597 issue = Issue.new
2618 issue = Issue.new
2598 issue.tracker = Tracker.find(1)
2619 issue.tracker = Tracker.find(1)
2599 assert_not_nil issue.status
2620 assert_not_nil issue.status
2600 assert_equal issue.default_status, issue.status
2621 assert_equal issue.default_status, issue.status
2601 end
2622 end
2602
2623
2603 def test_changing_tracker_should_set_default_status_if_status_was_default
2624 def test_changing_tracker_should_set_default_status_if_status_was_default
2604 WorkflowTransition.delete_all
2625 WorkflowTransition.delete_all
2605 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1
2626 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1
2606 Tracker.find(2).update! :default_status_id => 2
2627 Tracker.find(2).update! :default_status_id => 2
2607
2628
2608 issue = Issue.new(:tracker_id => 1, :status_id => 1)
2629 issue = Issue.new(:tracker_id => 1, :status_id => 1)
2609 assert_equal IssueStatus.find(1), issue.status
2630 assert_equal IssueStatus.find(1), issue.status
2610 issue.tracker = Tracker.find(2)
2631 issue.tracker = Tracker.find(2)
2611 assert_equal IssueStatus.find(2), issue.status
2632 assert_equal IssueStatus.find(2), issue.status
2612 end
2633 end
2613
2634
2614 def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker
2635 def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker
2615 WorkflowTransition.delete_all
2636 WorkflowTransition.delete_all
2616 Tracker.find(2).update! :default_status_id => 2
2637 Tracker.find(2).update! :default_status_id => 2
2617
2638
2618 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2639 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2619 assert_equal IssueStatus.find(3), issue.status
2640 assert_equal IssueStatus.find(3), issue.status
2620 issue.tracker = Tracker.find(2)
2641 issue.tracker = Tracker.find(2)
2621 assert_equal IssueStatus.find(2), issue.status
2642 assert_equal IssueStatus.find(2), issue.status
2622 end
2643 end
2623
2644
2624 def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker
2645 def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker
2625 WorkflowTransition.delete_all
2646 WorkflowTransition.delete_all
2626 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3
2647 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3
2627 Tracker.find(2).update! :default_status_id => 2
2648 Tracker.find(2).update! :default_status_id => 2
2628
2649
2629 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2650 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2630 assert_equal IssueStatus.find(3), issue.status
2651 assert_equal IssueStatus.find(3), issue.status
2631 issue.tracker = Tracker.find(2)
2652 issue.tracker = Tracker.find(2)
2632 assert_equal IssueStatus.find(3), issue.status
2653 assert_equal IssueStatus.find(3), issue.status
2633 end
2654 end
2634
2655
2635 def test_assigned_to_was_with_a_group
2656 def test_assigned_to_was_with_a_group
2636 group = Group.find(10)
2657 group = Group.find(10)
2637
2658
2638 issue = Issue.generate!(:assigned_to => group)
2659 issue = Issue.generate!(:assigned_to => group)
2639 issue.reload.assigned_to = nil
2660 issue.reload.assigned_to = nil
2640 assert_equal group, issue.assigned_to_was
2661 assert_equal group, issue.assigned_to_was
2641 end
2662 end
2642 end
2663 end
@@ -1,152 +1,162
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class MemberTest < ActiveSupport::TestCase
20 class MemberTest < ActiveSupport::TestCase
21 fixtures :projects, :trackers, :issue_statuses, :issues,
21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 :enumerations, :users, :issue_categories,
22 :enumerations, :users, :issue_categories,
23 :projects_trackers,
23 :projects_trackers,
24 :roles,
24 :roles,
25 :member_roles,
25 :member_roles,
26 :members,
26 :members,
27 :enabled_modules,
27 :enabled_modules,
28 :groups_users,
28 :groups_users,
29 :watchers,
29 :watchers,
30 :journals, :journal_details,
30 :journals, :journal_details,
31 :messages,
31 :messages,
32 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
32 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
33 :boards
33 :boards
34
34
35 include Redmine::I18n
35 include Redmine::I18n
36
36
37 def setup
37 def setup
38 @jsmith = Member.find(1)
38 @jsmith = Member.find(1)
39 end
39 end
40
40
41 def test_create
41 def test_create
42 member = Member.new(:project_id => 1, :user_id => 4, :role_ids => [1, 2])
42 member = Member.new(:project_id => 1, :user_id => 4, :role_ids => [1, 2])
43 assert member.save
43 assert member.save
44 member.reload
44 member.reload
45
45
46 assert_equal 2, member.roles.size
46 assert_equal 2, member.roles.size
47 assert_equal Role.find(1), member.roles.sort.first
47 assert_equal Role.find(1), member.roles.sort.first
48 end
48 end
49
49
50 def test_update
50 def test_update
51 assert_equal "eCookbook", @jsmith.project.name
51 assert_equal "eCookbook", @jsmith.project.name
52 assert_equal "Manager", @jsmith.roles.first.name
52 assert_equal "Manager", @jsmith.roles.first.name
53 assert_equal "jsmith", @jsmith.user.login
53 assert_equal "jsmith", @jsmith.user.login
54
54
55 @jsmith.mail_notification = !@jsmith.mail_notification
55 @jsmith.mail_notification = !@jsmith.mail_notification
56 assert @jsmith.save
56 assert @jsmith.save
57 end
57 end
58
58
59 def test_update_roles
59 def test_update_roles
60 assert_equal 1, @jsmith.roles.size
60 assert_equal 1, @jsmith.roles.size
61 @jsmith.role_ids = [1, 2]
61 @jsmith.role_ids = [1, 2]
62 assert @jsmith.save
62 assert @jsmith.save
63 assert_equal 2, @jsmith.reload.roles.size
63 assert_equal 2, @jsmith.reload.roles.size
64 end
64 end
65
65
66 def test_validate
66 def test_validate
67 member = Member.new(:project_id => 1, :user_id => 2, :role_ids => [2])
67 member = Member.new(:project_id => 1, :user_id => 2, :role_ids => [2])
68 # same use cannot have more than one membership for a project
68 # same use cannot have more than one membership for a project
69 assert !member.save
69 assert !member.save
70
70
71 # must have one role at least
71 # must have one role at least
72 user = User.new(:firstname => "new1", :lastname => "user1",
72 user = User.new(:firstname => "new1", :lastname => "user1",
73 :mail => "test_validate@somenet.foo")
73 :mail => "test_validate@somenet.foo")
74 user.login = "test_validate"
74 user.login = "test_validate"
75 user.password, user.password_confirmation = "password", "password"
75 user.password, user.password_confirmation = "password", "password"
76 assert user.save
76 assert user.save
77
77
78 set_language_if_valid 'fr'
78 set_language_if_valid 'fr'
79 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
79 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
80 assert !member.save
80 assert !member.save
81 assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
81 assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
82 assert_equal "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8'),
82 assert_equal "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8'),
83 [member.errors.full_messages].flatten.join
83 [member.errors.full_messages].flatten.join
84 end
84 end
85
85
86 def test_validate_member_role
86 def test_validate_member_role
87 user = User.new(:firstname => "new1", :lastname => "user1",
87 user = User.new(:firstname => "new1", :lastname => "user1",
88 :mail => "test_validate@somenet.foo")
88 :mail => "test_validate@somenet.foo")
89 user.login = "test_validate_member_role"
89 user.login = "test_validate_member_role"
90 user.password, user.password_confirmation = "password", "password"
90 user.password, user.password_confirmation = "password", "password"
91 assert user.save
91 assert user.save
92 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [5])
92 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [5])
93 assert !member.save
93 assert !member.save
94 end
94 end
95
95
96 def test_set_issue_category_nil_should_handle_nil_values
96 def test_set_issue_category_nil_should_handle_nil_values
97 m = Member.new
97 m = Member.new
98 assert_nil m.user
98 assert_nil m.user
99 assert_nil m.project
99 assert_nil m.project
100
100
101 assert_nothing_raised do
101 assert_nothing_raised do
102 m.set_issue_category_nil
102 m.set_issue_category_nil
103 end
103 end
104 end
104 end
105
105
106 def test_destroy
106 def test_destroy
107 category1 = IssueCategory.find(1)
107 category1 = IssueCategory.find(1)
108 assert_equal @jsmith.user.id, category1.assigned_to_id
108 assert_equal @jsmith.user.id, category1.assigned_to_id
109 assert_difference 'Member.count', -1 do
109 assert_difference 'Member.count', -1 do
110 assert_difference 'MemberRole.count', -1 do
110 assert_difference 'MemberRole.count', -1 do
111 @jsmith.destroy
111 @jsmith.destroy
112 end
112 end
113 end
113 end
114 assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
114 assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
115 category1.reload
115 category1.reload
116 assert_nil category1.assigned_to_id
116 assert_nil category1.assigned_to_id
117 end
117 end
118
118
119 def test_destroy_should_trigger_callbacks_only_once
119 def test_destroy_should_trigger_callbacks_only_once
120 Member.class_eval { def destroy_test_callback; end}
120 Member.class_eval { def destroy_test_callback; end}
121 Member.after_destroy :destroy_test_callback
121 Member.after_destroy :destroy_test_callback
122
122
123 m = Member.create!(:user_id => 1, :project_id => 1, :role_ids => [1,3])
123 m = Member.create!(:user_id => 1, :project_id => 1, :role_ids => [1,3])
124
124
125 Member.any_instance.expects(:destroy_test_callback).once
125 Member.any_instance.expects(:destroy_test_callback).once
126 assert_difference 'Member.count', -1 do
126 assert_difference 'Member.count', -1 do
127 assert_difference 'MemberRole.count', -2 do
127 assert_difference 'MemberRole.count', -2 do
128 m.destroy
128 m.destroy
129 end
129 end
130 end
130 end
131 assert m.destroyed?
131 assert m.destroyed?
132 ensure
132 ensure
133 Member._destroy_callbacks.delete(:destroy_test_callback)
133 Member._destroy_callbacks.delete(:destroy_test_callback)
134 end
134 end
135
135
136 def test_roles_should_be_unique
137 m = Member.new(:user_id => 1, :project_id => 1)
138 m.member_roles.build(:role_id => 1)
139 m.member_roles.build(:role_id => 1)
140 m.save!
141 m.reload
142 assert_equal 1, m.roles.count
143 assert_equal [1], m.roles.ids
144 end
145
136 def test_sort_without_roles
146 def test_sort_without_roles
137 a = Member.new(:roles => [Role.first])
147 a = Member.new(:roles => [Role.first])
138 b = Member.new
148 b = Member.new
139
149
140 assert_equal -1, a <=> b
150 assert_equal -1, a <=> b
141 assert_equal 1, b <=> a
151 assert_equal 1, b <=> a
142 end
152 end
143
153
144 def test_sort_without_principal
154 def test_sort_without_principal
145 role = Role.first
155 role = Role.first
146 a = Member.new(:roles => [role], :principal => User.first)
156 a = Member.new(:roles => [role], :principal => User.first)
147 b = Member.new(:roles => [role])
157 b = Member.new(:roles => [role])
148
158
149 assert_equal -1, a <=> b
159 assert_equal -1, a <=> b
150 assert_equal 1, b <=> a
160 assert_equal 1, b <=> a
151 end
161 end
152 end
162 end
@@ -1,1216 +1,1228
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class UserTest < ActiveSupport::TestCase
20 class UserTest < ActiveSupport::TestCase
21 fixtures :users, :email_addresses, :members, :projects, :roles, :member_roles, :auth_sources,
21 fixtures :users, :email_addresses, :members, :projects, :roles, :member_roles, :auth_sources,
22 :trackers, :issue_statuses,
22 :trackers, :issue_statuses,
23 :projects_trackers,
23 :projects_trackers,
24 :watchers,
24 :watchers,
25 :issue_categories, :enumerations, :issues,
25 :issue_categories, :enumerations, :issues,
26 :journals, :journal_details,
26 :journals, :journal_details,
27 :groups_users,
27 :groups_users,
28 :enabled_modules
28 :enabled_modules
29
29
30 include Redmine::I18n
30 include Redmine::I18n
31
31
32 def setup
32 def setup
33 @admin = User.find(1)
33 @admin = User.find(1)
34 @jsmith = User.find(2)
34 @jsmith = User.find(2)
35 @dlopper = User.find(3)
35 @dlopper = User.find(3)
36 end
36 end
37
37
38 def test_sorted_scope_should_sort_user_by_display_name
38 def test_sorted_scope_should_sort_user_by_display_name
39 # Use .active to ignore anonymous with localized display name
39 # Use .active to ignore anonymous with localized display name
40 assert_equal User.active.map(&:name).map(&:downcase).sort,
40 assert_equal User.active.map(&:name).map(&:downcase).sort,
41 User.active.sorted.map(&:name).map(&:downcase)
41 User.active.sorted.map(&:name).map(&:downcase)
42 end
42 end
43
43
44 def test_generate
44 def test_generate
45 User.generate!(:firstname => 'Testing connection')
45 User.generate!(:firstname => 'Testing connection')
46 User.generate!(:firstname => 'Testing connection')
46 User.generate!(:firstname => 'Testing connection')
47 assert_equal 2, User.where(:firstname => 'Testing connection').count
47 assert_equal 2, User.where(:firstname => 'Testing connection').count
48 end
48 end
49
49
50 def test_truth
50 def test_truth
51 assert_kind_of User, @jsmith
51 assert_kind_of User, @jsmith
52 end
52 end
53
53
54 def test_mail_should_be_stripped
54 def test_mail_should_be_stripped
55 u = User.new
55 u = User.new
56 u.mail = " foo@bar.com "
56 u.mail = " foo@bar.com "
57 assert_equal "foo@bar.com", u.mail
57 assert_equal "foo@bar.com", u.mail
58 end
58 end
59
59
60 def test_should_create_email_address
60 def test_should_create_email_address
61 u = User.new(:firstname => "new", :lastname => "user")
61 u = User.new(:firstname => "new", :lastname => "user")
62 u.login = "create_email_address"
62 u.login = "create_email_address"
63 u.mail = "defaultemail@somenet.foo"
63 u.mail = "defaultemail@somenet.foo"
64 assert u.save
64 assert u.save
65 u.reload
65 u.reload
66 assert u.email_address
66 assert u.email_address
67 assert_equal "defaultemail@somenet.foo", u.email_address.address
67 assert_equal "defaultemail@somenet.foo", u.email_address.address
68 assert_equal true, u.email_address.is_default
68 assert_equal true, u.email_address.is_default
69 assert_equal true, u.email_address.notify
69 assert_equal true, u.email_address.notify
70 end
70 end
71
71
72 def test_should_not_create_user_without_mail
72 def test_should_not_create_user_without_mail
73 set_language_if_valid 'en'
73 set_language_if_valid 'en'
74 u = User.new(:firstname => "new", :lastname => "user")
74 u = User.new(:firstname => "new", :lastname => "user")
75 u.login = "user_without_mail"
75 u.login = "user_without_mail"
76 assert !u.save
76 assert !u.save
77 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
77 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
78 end
78 end
79
79
80 def test_should_not_create_user_with_blank_mail
80 def test_should_not_create_user_with_blank_mail
81 set_language_if_valid 'en'
81 set_language_if_valid 'en'
82 u = User.new(:firstname => "new", :lastname => "user")
82 u = User.new(:firstname => "new", :lastname => "user")
83 u.login = "user_with_blank_mail"
83 u.login = "user_with_blank_mail"
84 u.mail = ''
84 u.mail = ''
85 assert !u.save
85 assert !u.save
86 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
86 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
87 end
87 end
88
88
89 def test_should_not_update_user_with_blank_mail
89 def test_should_not_update_user_with_blank_mail
90 set_language_if_valid 'en'
90 set_language_if_valid 'en'
91 u = User.find(2)
91 u = User.find(2)
92 u.mail = ''
92 u.mail = ''
93 assert !u.save
93 assert !u.save
94 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
94 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
95 end
95 end
96
96
97 def test_login_length_validation
97 def test_login_length_validation
98 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
98 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
99 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
99 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
100 assert !user.valid?
100 assert !user.valid?
101
101
102 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
102 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
103 assert user.valid?
103 assert user.valid?
104 assert user.save
104 assert user.save
105 end
105 end
106
106
107 def test_generate_password_should_respect_minimum_password_length
107 def test_generate_password_should_respect_minimum_password_length
108 with_settings :password_min_length => 15 do
108 with_settings :password_min_length => 15 do
109 user = User.generate!(:generate_password => true)
109 user = User.generate!(:generate_password => true)
110 assert user.password.length >= 15
110 assert user.password.length >= 15
111 end
111 end
112 end
112 end
113
113
114 def test_generate_password_should_not_generate_password_with_less_than_10_characters
114 def test_generate_password_should_not_generate_password_with_less_than_10_characters
115 with_settings :password_min_length => 4 do
115 with_settings :password_min_length => 4 do
116 user = User.generate!(:generate_password => true)
116 user = User.generate!(:generate_password => true)
117 assert user.password.length >= 10
117 assert user.password.length >= 10
118 end
118 end
119 end
119 end
120
120
121 def test_generate_password_on_create_should_set_password
121 def test_generate_password_on_create_should_set_password
122 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
122 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
123 user.login = "newuser"
123 user.login = "newuser"
124 user.generate_password = true
124 user.generate_password = true
125 assert user.save
125 assert user.save
126
126
127 password = user.password
127 password = user.password
128 assert user.check_password?(password)
128 assert user.check_password?(password)
129 end
129 end
130
130
131 def test_generate_password_on_update_should_update_password
131 def test_generate_password_on_update_should_update_password
132 user = User.find(2)
132 user = User.find(2)
133 hash = user.hashed_password
133 hash = user.hashed_password
134 user.generate_password = true
134 user.generate_password = true
135 assert user.save
135 assert user.save
136
136
137 password = user.password
137 password = user.password
138 assert user.check_password?(password)
138 assert user.check_password?(password)
139 assert_not_equal hash, user.reload.hashed_password
139 assert_not_equal hash, user.reload.hashed_password
140 end
140 end
141
141
142 def test_create
142 def test_create
143 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
143 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
144
144
145 user.login = "jsmith"
145 user.login = "jsmith"
146 user.password, user.password_confirmation = "password", "password"
146 user.password, user.password_confirmation = "password", "password"
147 # login uniqueness
147 # login uniqueness
148 assert !user.save
148 assert !user.save
149 assert_equal 1, user.errors.count
149 assert_equal 1, user.errors.count
150
150
151 user.login = "newuser"
151 user.login = "newuser"
152 user.password, user.password_confirmation = "password", "pass"
152 user.password, user.password_confirmation = "password", "pass"
153 # password confirmation
153 # password confirmation
154 assert !user.save
154 assert !user.save
155 assert_equal 1, user.errors.count
155 assert_equal 1, user.errors.count
156
156
157 user.password, user.password_confirmation = "password", "password"
157 user.password, user.password_confirmation = "password", "password"
158 assert user.save
158 assert user.save
159 end
159 end
160
160
161 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
161 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
162 @user1 = User.generate!
162 @user1 = User.generate!
163 assert_equal 'only_my_events', @user1.mail_notification
163 assert_equal 'only_my_events', @user1.mail_notification
164 with_settings :default_notification_option => 'all' do
164 with_settings :default_notification_option => 'all' do
165 @user2 = User.generate!
165 @user2 = User.generate!
166 assert_equal 'all', @user2.mail_notification
166 assert_equal 'all', @user2.mail_notification
167 end
167 end
168 end
168 end
169
169
170 def test_user_login_should_be_case_insensitive
170 def test_user_login_should_be_case_insensitive
171 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
171 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
172 u.login = 'newuser'
172 u.login = 'newuser'
173 u.password, u.password_confirmation = "password", "password"
173 u.password, u.password_confirmation = "password", "password"
174 assert u.save
174 assert u.save
175 u = User.new(:firstname => "Similar", :lastname => "User",
175 u = User.new(:firstname => "Similar", :lastname => "User",
176 :mail => "similaruser@somenet.foo")
176 :mail => "similaruser@somenet.foo")
177 u.login = 'NewUser'
177 u.login = 'NewUser'
178 u.password, u.password_confirmation = "password", "password"
178 u.password, u.password_confirmation = "password", "password"
179 assert !u.save
179 assert !u.save
180 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
180 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
181 end
181 end
182
182
183 def test_mail_uniqueness_should_not_be_case_sensitive
183 def test_mail_uniqueness_should_not_be_case_sensitive
184 set_language_if_valid 'en'
184 set_language_if_valid 'en'
185 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
185 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
186 u.login = 'newuser1'
186 u.login = 'newuser1'
187 u.password, u.password_confirmation = "password", "password"
187 u.password, u.password_confirmation = "password", "password"
188 assert u.save
188 assert u.save
189
189
190 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
190 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
191 u.login = 'newuser2'
191 u.login = 'newuser2'
192 u.password, u.password_confirmation = "password", "password"
192 u.password, u.password_confirmation = "password", "password"
193 assert !u.save
193 assert !u.save
194 assert_include "Email #{I18n.translate('activerecord.errors.messages.taken')}", u.errors.full_messages
194 assert_include "Email #{I18n.translate('activerecord.errors.messages.taken')}", u.errors.full_messages
195 end
195 end
196
196
197 def test_update
197 def test_update
198 assert_equal "admin", @admin.login
198 assert_equal "admin", @admin.login
199 @admin.login = "john"
199 @admin.login = "john"
200 assert @admin.save, @admin.errors.full_messages.join("; ")
200 assert @admin.save, @admin.errors.full_messages.join("; ")
201 @admin.reload
201 @admin.reload
202 assert_equal "john", @admin.login
202 assert_equal "john", @admin.login
203 end
203 end
204
204
205 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
205 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
206 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
206 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
207 u1.login = 'newuser1'
207 u1.login = 'newuser1'
208 assert u1.save
208 assert u1.save
209
209
210 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
210 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
211 u2.login = 'newuser1'
211 u2.login = 'newuser1'
212 assert u2.save(:validate => false)
212 assert u2.save(:validate => false)
213
213
214 user = User.find(u2.id)
214 user = User.find(u2.id)
215 user.firstname = "firstname"
215 user.firstname = "firstname"
216 assert user.save, "Save failed"
216 assert user.save, "Save failed"
217 end
217 end
218
218
219 def test_destroy_should_delete_members_and_roles
219 def test_destroy_should_delete_members_and_roles
220 members = Member.where(:user_id => 2)
220 members = Member.where(:user_id => 2)
221 ms = members.count
221 ms = members.count
222 rs = members.collect(&:roles).flatten.size
222 rs = members.collect(&:roles).flatten.size
223 assert ms > 0
223 assert ms > 0
224 assert rs > 0
224 assert rs > 0
225 assert_difference 'Member.count', - ms do
225 assert_difference 'Member.count', - ms do
226 assert_difference 'MemberRole.count', - rs do
226 assert_difference 'MemberRole.count', - rs do
227 User.find(2).destroy
227 User.find(2).destroy
228 end
228 end
229 end
229 end
230 assert_nil User.find_by_id(2)
230 assert_nil User.find_by_id(2)
231 assert_equal 0, Member.where(:user_id => 2).count
231 assert_equal 0, Member.where(:user_id => 2).count
232 end
232 end
233
233
234 def test_destroy_should_update_attachments
234 def test_destroy_should_update_attachments
235 attachment = Attachment.create!(:container => Project.find(1),
235 attachment = Attachment.create!(:container => Project.find(1),
236 :file => uploaded_test_file("testfile.txt", "text/plain"),
236 :file => uploaded_test_file("testfile.txt", "text/plain"),
237 :author_id => 2)
237 :author_id => 2)
238
238
239 User.find(2).destroy
239 User.find(2).destroy
240 assert_nil User.find_by_id(2)
240 assert_nil User.find_by_id(2)
241 assert_equal User.anonymous, attachment.reload.author
241 assert_equal User.anonymous, attachment.reload.author
242 end
242 end
243
243
244 def test_destroy_should_update_comments
244 def test_destroy_should_update_comments
245 comment = Comment.create!(
245 comment = Comment.create!(
246 :commented => News.create!(:project_id => 1,
246 :commented => News.create!(:project_id => 1,
247 :author_id => 1, :title => 'foo', :description => 'foo'),
247 :author_id => 1, :title => 'foo', :description => 'foo'),
248 :author => User.find(2),
248 :author => User.find(2),
249 :comments => 'foo'
249 :comments => 'foo'
250 )
250 )
251
251
252 User.find(2).destroy
252 User.find(2).destroy
253 assert_nil User.find_by_id(2)
253 assert_nil User.find_by_id(2)
254 assert_equal User.anonymous, comment.reload.author
254 assert_equal User.anonymous, comment.reload.author
255 end
255 end
256
256
257 def test_destroy_should_update_issues
257 def test_destroy_should_update_issues
258 issue = Issue.create!(:project_id => 1, :author_id => 2,
258 issue = Issue.create!(:project_id => 1, :author_id => 2,
259 :tracker_id => 1, :subject => 'foo')
259 :tracker_id => 1, :subject => 'foo')
260
260
261 User.find(2).destroy
261 User.find(2).destroy
262 assert_nil User.find_by_id(2)
262 assert_nil User.find_by_id(2)
263 assert_equal User.anonymous, issue.reload.author
263 assert_equal User.anonymous, issue.reload.author
264 end
264 end
265
265
266 def test_destroy_should_unassign_issues
266 def test_destroy_should_unassign_issues
267 issue = Issue.create!(:project_id => 1, :author_id => 1,
267 issue = Issue.create!(:project_id => 1, :author_id => 1,
268 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
268 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
269
269
270 User.find(2).destroy
270 User.find(2).destroy
271 assert_nil User.find_by_id(2)
271 assert_nil User.find_by_id(2)
272 assert_nil issue.reload.assigned_to
272 assert_nil issue.reload.assigned_to
273 end
273 end
274
274
275 def test_destroy_should_update_journals
275 def test_destroy_should_update_journals
276 issue = Issue.create!(:project_id => 1, :author_id => 2,
276 issue = Issue.create!(:project_id => 1, :author_id => 2,
277 :tracker_id => 1, :subject => 'foo')
277 :tracker_id => 1, :subject => 'foo')
278 issue.init_journal(User.find(2), "update")
278 issue.init_journal(User.find(2), "update")
279 issue.save!
279 issue.save!
280
280
281 User.find(2).destroy
281 User.find(2).destroy
282 assert_nil User.find_by_id(2)
282 assert_nil User.find_by_id(2)
283 assert_equal User.anonymous, issue.journals.first.reload.user
283 assert_equal User.anonymous, issue.journals.first.reload.user
284 end
284 end
285
285
286 def test_destroy_should_update_journal_details_old_value
286 def test_destroy_should_update_journal_details_old_value
287 issue = Issue.create!(:project_id => 1, :author_id => 1,
287 issue = Issue.create!(:project_id => 1, :author_id => 1,
288 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
288 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
289 issue.init_journal(User.find(1), "update")
289 issue.init_journal(User.find(1), "update")
290 issue.assigned_to_id = nil
290 issue.assigned_to_id = nil
291 assert_difference 'JournalDetail.count' do
291 assert_difference 'JournalDetail.count' do
292 issue.save!
292 issue.save!
293 end
293 end
294 journal_detail = JournalDetail.order('id DESC').first
294 journal_detail = JournalDetail.order('id DESC').first
295 assert_equal '2', journal_detail.old_value
295 assert_equal '2', journal_detail.old_value
296
296
297 User.find(2).destroy
297 User.find(2).destroy
298 assert_nil User.find_by_id(2)
298 assert_nil User.find_by_id(2)
299 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
299 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
300 end
300 end
301
301
302 def test_destroy_should_update_journal_details_value
302 def test_destroy_should_update_journal_details_value
303 issue = Issue.create!(:project_id => 1, :author_id => 1,
303 issue = Issue.create!(:project_id => 1, :author_id => 1,
304 :tracker_id => 1, :subject => 'foo')
304 :tracker_id => 1, :subject => 'foo')
305 issue.init_journal(User.find(1), "update")
305 issue.init_journal(User.find(1), "update")
306 issue.assigned_to_id = 2
306 issue.assigned_to_id = 2
307 assert_difference 'JournalDetail.count' do
307 assert_difference 'JournalDetail.count' do
308 issue.save!
308 issue.save!
309 end
309 end
310 journal_detail = JournalDetail.order('id DESC').first
310 journal_detail = JournalDetail.order('id DESC').first
311 assert_equal '2', journal_detail.value
311 assert_equal '2', journal_detail.value
312
312
313 User.find(2).destroy
313 User.find(2).destroy
314 assert_nil User.find_by_id(2)
314 assert_nil User.find_by_id(2)
315 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
315 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
316 end
316 end
317
317
318 def test_destroy_should_update_messages
318 def test_destroy_should_update_messages
319 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
319 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
320 message = Message.create!(:board_id => board.id, :author_id => 2,
320 message = Message.create!(:board_id => board.id, :author_id => 2,
321 :subject => 'foo', :content => 'foo')
321 :subject => 'foo', :content => 'foo')
322 User.find(2).destroy
322 User.find(2).destroy
323 assert_nil User.find_by_id(2)
323 assert_nil User.find_by_id(2)
324 assert_equal User.anonymous, message.reload.author
324 assert_equal User.anonymous, message.reload.author
325 end
325 end
326
326
327 def test_destroy_should_update_news
327 def test_destroy_should_update_news
328 news = News.create!(:project_id => 1, :author_id => 2,
328 news = News.create!(:project_id => 1, :author_id => 2,
329 :title => 'foo', :description => 'foo')
329 :title => 'foo', :description => 'foo')
330 User.find(2).destroy
330 User.find(2).destroy
331 assert_nil User.find_by_id(2)
331 assert_nil User.find_by_id(2)
332 assert_equal User.anonymous, news.reload.author
332 assert_equal User.anonymous, news.reload.author
333 end
333 end
334
334
335 def test_destroy_should_delete_private_queries
335 def test_destroy_should_delete_private_queries
336 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
336 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
337 query.project_id = 1
337 query.project_id = 1
338 query.user_id = 2
338 query.user_id = 2
339 query.save!
339 query.save!
340
340
341 User.find(2).destroy
341 User.find(2).destroy
342 assert_nil User.find_by_id(2)
342 assert_nil User.find_by_id(2)
343 assert_nil Query.find_by_id(query.id)
343 assert_nil Query.find_by_id(query.id)
344 end
344 end
345
345
346 def test_destroy_should_update_public_queries
346 def test_destroy_should_update_public_queries
347 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
347 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
348 query.project_id = 1
348 query.project_id = 1
349 query.user_id = 2
349 query.user_id = 2
350 query.save!
350 query.save!
351
351
352 User.find(2).destroy
352 User.find(2).destroy
353 assert_nil User.find_by_id(2)
353 assert_nil User.find_by_id(2)
354 assert_equal User.anonymous, query.reload.user
354 assert_equal User.anonymous, query.reload.user
355 end
355 end
356
356
357 def test_destroy_should_update_time_entries
357 def test_destroy_should_update_time_entries
358 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
358 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
359 :activity => TimeEntryActivity.create!(:name => 'foo'))
359 :activity => TimeEntryActivity.create!(:name => 'foo'))
360 entry.project_id = 1
360 entry.project_id = 1
361 entry.user_id = 2
361 entry.user_id = 2
362 entry.save!
362 entry.save!
363
363
364 User.find(2).destroy
364 User.find(2).destroy
365 assert_nil User.find_by_id(2)
365 assert_nil User.find_by_id(2)
366 assert_equal User.anonymous, entry.reload.user
366 assert_equal User.anonymous, entry.reload.user
367 end
367 end
368
368
369 def test_destroy_should_delete_tokens
369 def test_destroy_should_delete_tokens
370 token = Token.create!(:user_id => 2, :value => 'foo')
370 token = Token.create!(:user_id => 2, :value => 'foo')
371
371
372 User.find(2).destroy
372 User.find(2).destroy
373 assert_nil User.find_by_id(2)
373 assert_nil User.find_by_id(2)
374 assert_nil Token.find_by_id(token.id)
374 assert_nil Token.find_by_id(token.id)
375 end
375 end
376
376
377 def test_destroy_should_delete_watchers
377 def test_destroy_should_delete_watchers
378 issue = Issue.create!(:project_id => 1, :author_id => 1,
378 issue = Issue.create!(:project_id => 1, :author_id => 1,
379 :tracker_id => 1, :subject => 'foo')
379 :tracker_id => 1, :subject => 'foo')
380 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
380 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
381
381
382 User.find(2).destroy
382 User.find(2).destroy
383 assert_nil User.find_by_id(2)
383 assert_nil User.find_by_id(2)
384 assert_nil Watcher.find_by_id(watcher.id)
384 assert_nil Watcher.find_by_id(watcher.id)
385 end
385 end
386
386
387 def test_destroy_should_update_wiki_contents
387 def test_destroy_should_update_wiki_contents
388 wiki_content = WikiContent.create!(
388 wiki_content = WikiContent.create!(
389 :text => 'foo',
389 :text => 'foo',
390 :author_id => 2,
390 :author_id => 2,
391 :page => WikiPage.create!(:title => 'Foo',
391 :page => WikiPage.create!(:title => 'Foo',
392 :wiki => Wiki.create!(:project_id => 3,
392 :wiki => Wiki.create!(:project_id => 3,
393 :start_page => 'Start'))
393 :start_page => 'Start'))
394 )
394 )
395 wiki_content.text = 'bar'
395 wiki_content.text = 'bar'
396 assert_difference 'WikiContent::Version.count' do
396 assert_difference 'WikiContent::Version.count' do
397 wiki_content.save!
397 wiki_content.save!
398 end
398 end
399
399
400 User.find(2).destroy
400 User.find(2).destroy
401 assert_nil User.find_by_id(2)
401 assert_nil User.find_by_id(2)
402 assert_equal User.anonymous, wiki_content.reload.author
402 assert_equal User.anonymous, wiki_content.reload.author
403 wiki_content.versions.each do |version|
403 wiki_content.versions.each do |version|
404 assert_equal User.anonymous, version.reload.author
404 assert_equal User.anonymous, version.reload.author
405 end
405 end
406 end
406 end
407
407
408 def test_destroy_should_nullify_issue_categories
408 def test_destroy_should_nullify_issue_categories
409 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
409 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
410
410
411 User.find(2).destroy
411 User.find(2).destroy
412 assert_nil User.find_by_id(2)
412 assert_nil User.find_by_id(2)
413 assert_nil category.reload.assigned_to_id
413 assert_nil category.reload.assigned_to_id
414 end
414 end
415
415
416 def test_destroy_should_nullify_changesets
416 def test_destroy_should_nullify_changesets
417 changeset = Changeset.create!(
417 changeset = Changeset.create!(
418 :repository => Repository::Subversion.create!(
418 :repository => Repository::Subversion.create!(
419 :project_id => 1,
419 :project_id => 1,
420 :url => 'file:///tmp',
420 :url => 'file:///tmp',
421 :identifier => 'tmp'
421 :identifier => 'tmp'
422 ),
422 ),
423 :revision => '12',
423 :revision => '12',
424 :committed_on => Time.now,
424 :committed_on => Time.now,
425 :committer => 'jsmith'
425 :committer => 'jsmith'
426 )
426 )
427 assert_equal 2, changeset.user_id
427 assert_equal 2, changeset.user_id
428
428
429 User.find(2).destroy
429 User.find(2).destroy
430 assert_nil User.find_by_id(2)
430 assert_nil User.find_by_id(2)
431 assert_nil changeset.reload.user_id
431 assert_nil changeset.reload.user_id
432 end
432 end
433
433
434 def test_anonymous_user_should_not_be_destroyable
434 def test_anonymous_user_should_not_be_destroyable
435 assert_no_difference 'User.count' do
435 assert_no_difference 'User.count' do
436 assert_equal false, User.anonymous.destroy
436 assert_equal false, User.anonymous.destroy
437 end
437 end
438 end
438 end
439
439
440 def test_password_change_should_destroy_tokens
440 def test_password_change_should_destroy_tokens
441 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
441 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
442 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
442 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
443
443
444 user = User.find(2)
444 user = User.find(2)
445 user.password, user.password_confirmation = "a new password", "a new password"
445 user.password, user.password_confirmation = "a new password", "a new password"
446 assert user.save
446 assert user.save
447
447
448 assert_nil Token.find_by_id(recovery_token.id)
448 assert_nil Token.find_by_id(recovery_token.id)
449 assert_nil Token.find_by_id(autologin_token.id)
449 assert_nil Token.find_by_id(autologin_token.id)
450 end
450 end
451
451
452 def test_mail_change_should_destroy_tokens
452 def test_mail_change_should_destroy_tokens
453 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
453 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
454 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
454 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
455
455
456 user = User.find(2)
456 user = User.find(2)
457 user.mail = "user@somwehere.com"
457 user.mail = "user@somwehere.com"
458 assert user.save
458 assert user.save
459
459
460 assert_nil Token.find_by_id(recovery_token.id)
460 assert_nil Token.find_by_id(recovery_token.id)
461 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
461 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
462 end
462 end
463
463
464 def test_change_on_other_fields_should_not_destroy_tokens
464 def test_change_on_other_fields_should_not_destroy_tokens
465 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
465 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
466 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
466 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
467
467
468 user = User.find(2)
468 user = User.find(2)
469 user.firstname = "Bobby"
469 user.firstname = "Bobby"
470 assert user.save
470 assert user.save
471
471
472 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
472 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
473 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
473 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
474 end
474 end
475
475
476 def test_validate_login_presence
476 def test_validate_login_presence
477 @admin.login = ""
477 @admin.login = ""
478 assert !@admin.save
478 assert !@admin.save
479 assert_equal 1, @admin.errors.count
479 assert_equal 1, @admin.errors.count
480 end
480 end
481
481
482 def test_validate_mail_notification_inclusion
482 def test_validate_mail_notification_inclusion
483 u = User.new
483 u = User.new
484 u.mail_notification = 'foo'
484 u.mail_notification = 'foo'
485 u.save
485 u.save
486 assert_not_equal [], u.errors[:mail_notification]
486 assert_not_equal [], u.errors[:mail_notification]
487 end
487 end
488
488
489 def test_password
489 def test_password
490 user = User.try_to_login("admin", "admin")
490 user = User.try_to_login("admin", "admin")
491 assert_kind_of User, user
491 assert_kind_of User, user
492 assert_equal "admin", user.login
492 assert_equal "admin", user.login
493 user.password = "hello123"
493 user.password = "hello123"
494 assert user.save
494 assert user.save
495
495
496 user = User.try_to_login("admin", "hello123")
496 user = User.try_to_login("admin", "hello123")
497 assert_kind_of User, user
497 assert_kind_of User, user
498 assert_equal "admin", user.login
498 assert_equal "admin", user.login
499 end
499 end
500
500
501 def test_validate_password_length
501 def test_validate_password_length
502 with_settings :password_min_length => '100' do
502 with_settings :password_min_length => '100' do
503 user = User.new(:firstname => "new100",
503 user = User.new(:firstname => "new100",
504 :lastname => "user100", :mail => "newuser100@somenet.foo")
504 :lastname => "user100", :mail => "newuser100@somenet.foo")
505 user.login = "newuser100"
505 user.login = "newuser100"
506 user.password, user.password_confirmation = "password100", "password100"
506 user.password, user.password_confirmation = "password100", "password100"
507 assert !user.save
507 assert !user.save
508 assert_equal 1, user.errors.count
508 assert_equal 1, user.errors.count
509 end
509 end
510 end
510 end
511
511
512 def test_name_format
512 def test_name_format
513 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
513 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
514 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
514 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
515 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
515 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
516 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
516 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
517 end
517 end
518
518
519 def test_name_should_use_setting_as_default_format
519 def test_name_should_use_setting_as_default_format
520 with_settings :user_format => :firstname_lastname do
520 with_settings :user_format => :firstname_lastname do
521 assert_equal 'John Smith', @jsmith.reload.name
521 assert_equal 'John Smith', @jsmith.reload.name
522 end
522 end
523 with_settings :user_format => :username do
523 with_settings :user_format => :username do
524 assert_equal 'jsmith', @jsmith.reload.name
524 assert_equal 'jsmith', @jsmith.reload.name
525 end
525 end
526 with_settings :user_format => :lastname do
526 with_settings :user_format => :lastname do
527 assert_equal 'Smith', @jsmith.reload.name
527 assert_equal 'Smith', @jsmith.reload.name
528 end
528 end
529 end
529 end
530
530
531 def test_today_should_return_the_day_according_to_user_time_zone
531 def test_today_should_return_the_day_according_to_user_time_zone
532 preference = User.find(1).pref
532 preference = User.find(1).pref
533 date = Date.new(2012, 05, 15)
533 date = Date.new(2012, 05, 15)
534 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
534 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
535 Date.stubs(:today).returns(date)
535 Date.stubs(:today).returns(date)
536 Time.stubs(:now).returns(time)
536 Time.stubs(:now).returns(time)
537
537
538 preference.update_attribute :time_zone, 'Baku' # UTC+4
538 preference.update_attribute :time_zone, 'Baku' # UTC+4
539 assert_equal '2012-05-16', User.find(1).today.to_s
539 assert_equal '2012-05-16', User.find(1).today.to_s
540
540
541 preference.update_attribute :time_zone, 'La Paz' # UTC-4
541 preference.update_attribute :time_zone, 'La Paz' # UTC-4
542 assert_equal '2012-05-15', User.find(1).today.to_s
542 assert_equal '2012-05-15', User.find(1).today.to_s
543
543
544 preference.update_attribute :time_zone, ''
544 preference.update_attribute :time_zone, ''
545 assert_equal '2012-05-15', User.find(1).today.to_s
545 assert_equal '2012-05-15', User.find(1).today.to_s
546 end
546 end
547
547
548 def test_time_to_date_should_return_the_date_according_to_user_time_zone
548 def test_time_to_date_should_return_the_date_according_to_user_time_zone
549 preference = User.find(1).pref
549 preference = User.find(1).pref
550 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
550 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
551
551
552 preference.update_attribute :time_zone, 'Baku' # UTC+4
552 preference.update_attribute :time_zone, 'Baku' # UTC+4
553 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
553 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
554
554
555 preference.update_attribute :time_zone, 'La Paz' # UTC-4
555 preference.update_attribute :time_zone, 'La Paz' # UTC-4
556 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
556 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
557
557
558 preference.update_attribute :time_zone, ''
558 preference.update_attribute :time_zone, ''
559 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
559 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
560 end
560 end
561
561
562 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
562 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
563 with_settings :user_format => 'lastname_coma_firstname' do
563 with_settings :user_format => 'lastname_coma_firstname' do
564 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
564 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
565 User.fields_for_order_statement
565 User.fields_for_order_statement
566 end
566 end
567 end
567 end
568
568
569 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
569 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
570 with_settings :user_format => 'lastname_firstname' do
570 with_settings :user_format => 'lastname_firstname' do
571 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
571 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
572 User.fields_for_order_statement('authors')
572 User.fields_for_order_statement('authors')
573 end
573 end
574 end
574 end
575
575
576 def test_fields_for_order_statement_with_blank_format_should_return_default
576 def test_fields_for_order_statement_with_blank_format_should_return_default
577 with_settings :user_format => '' do
577 with_settings :user_format => '' do
578 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
578 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
579 User.fields_for_order_statement
579 User.fields_for_order_statement
580 end
580 end
581 end
581 end
582
582
583 def test_fields_for_order_statement_with_invalid_format_should_return_default
583 def test_fields_for_order_statement_with_invalid_format_should_return_default
584 with_settings :user_format => 'foo' do
584 with_settings :user_format => 'foo' do
585 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
585 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
586 User.fields_for_order_statement
586 User.fields_for_order_statement
587 end
587 end
588 end
588 end
589
589
590 test ".try_to_login with good credentials should return the user" do
590 test ".try_to_login with good credentials should return the user" do
591 user = User.try_to_login("admin", "admin")
591 user = User.try_to_login("admin", "admin")
592 assert_kind_of User, user
592 assert_kind_of User, user
593 assert_equal "admin", user.login
593 assert_equal "admin", user.login
594 end
594 end
595
595
596 test ".try_to_login with wrong credentials should return nil" do
596 test ".try_to_login with wrong credentials should return nil" do
597 assert_nil User.try_to_login("admin", "foo")
597 assert_nil User.try_to_login("admin", "foo")
598 end
598 end
599
599
600 def test_try_to_login_with_locked_user_should_return_nil
600 def test_try_to_login_with_locked_user_should_return_nil
601 @jsmith.status = User::STATUS_LOCKED
601 @jsmith.status = User::STATUS_LOCKED
602 @jsmith.save!
602 @jsmith.save!
603
603
604 user = User.try_to_login("jsmith", "jsmith")
604 user = User.try_to_login("jsmith", "jsmith")
605 assert_equal nil, user
605 assert_equal nil, user
606 end
606 end
607
607
608 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
608 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
609 @jsmith.status = User::STATUS_LOCKED
609 @jsmith.status = User::STATUS_LOCKED
610 @jsmith.save!
610 @jsmith.save!
611
611
612 user = User.try_to_login("jsmith", "jsmith", false)
612 user = User.try_to_login("jsmith", "jsmith", false)
613 assert_equal @jsmith, user
613 assert_equal @jsmith, user
614 end
614 end
615
615
616 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
616 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
617 user = User.try_to_login("AdMin", "admin")
617 user = User.try_to_login("AdMin", "admin")
618 assert_kind_of User, user
618 assert_kind_of User, user
619 assert_equal "admin", user.login
619 assert_equal "admin", user.login
620 end
620 end
621
621
622 test ".try_to_login should select the exact matching user first" do
622 test ".try_to_login should select the exact matching user first" do
623 case_sensitive_user = User.generate! do |user|
623 case_sensitive_user = User.generate! do |user|
624 user.password = "admin123"
624 user.password = "admin123"
625 end
625 end
626 # bypass validations to make it appear like existing data
626 # bypass validations to make it appear like existing data
627 case_sensitive_user.update_attribute(:login, 'ADMIN')
627 case_sensitive_user.update_attribute(:login, 'ADMIN')
628
628
629 user = User.try_to_login("ADMIN", "admin123")
629 user = User.try_to_login("ADMIN", "admin123")
630 assert_kind_of User, user
630 assert_kind_of User, user
631 assert_equal "ADMIN", user.login
631 assert_equal "ADMIN", user.login
632 end
632 end
633
633
634 if ldap_configured?
634 if ldap_configured?
635 test "#try_to_login using LDAP with failed connection to the LDAP server" do
635 test "#try_to_login using LDAP with failed connection to the LDAP server" do
636 auth_source = AuthSourceLdap.find(1)
636 auth_source = AuthSourceLdap.find(1)
637 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
637 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
638
638
639 assert_equal nil, User.try_to_login('edavis', 'wrong')
639 assert_equal nil, User.try_to_login('edavis', 'wrong')
640 end
640 end
641
641
642 test "#try_to_login using LDAP" do
642 test "#try_to_login using LDAP" do
643 assert_equal nil, User.try_to_login('edavis', 'wrong')
643 assert_equal nil, User.try_to_login('edavis', 'wrong')
644 end
644 end
645
645
646 test "#try_to_login using LDAP binding with user's account" do
646 test "#try_to_login using LDAP binding with user's account" do
647 auth_source = AuthSourceLdap.find(1)
647 auth_source = AuthSourceLdap.find(1)
648 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
648 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
649 auth_source.account_password = ''
649 auth_source.account_password = ''
650 auth_source.save!
650 auth_source.save!
651
651
652 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
652 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
653 ldap_user.login = 'example1'
653 ldap_user.login = 'example1'
654 ldap_user.save!
654 ldap_user.save!
655
655
656 assert_equal ldap_user, User.try_to_login('example1', '123456')
656 assert_equal ldap_user, User.try_to_login('example1', '123456')
657 assert_nil User.try_to_login('example1', '11111')
657 assert_nil User.try_to_login('example1', '11111')
658 end
658 end
659
659
660 test "#try_to_login using LDAP on the fly registration" do
660 test "#try_to_login using LDAP on the fly registration" do
661 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
661 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
662
662
663 assert_difference('User.count') do
663 assert_difference('User.count') do
664 assert User.try_to_login('edavis', '123456')
664 assert User.try_to_login('edavis', '123456')
665 end
665 end
666
666
667 assert_no_difference('User.count') do
667 assert_no_difference('User.count') do
668 assert User.try_to_login('edavis', '123456')
668 assert User.try_to_login('edavis', '123456')
669 end
669 end
670
670
671 assert_nil User.try_to_login('example1', '11111')
671 assert_nil User.try_to_login('example1', '11111')
672 end
672 end
673
673
674 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
674 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
675 auth_source = AuthSourceLdap.find(1)
675 auth_source = AuthSourceLdap.find(1)
676 auth_source.update_attribute :onthefly_register, true
676 auth_source.update_attribute :onthefly_register, true
677 auth_source = AuthSourceLdap.find(1)
677 auth_source = AuthSourceLdap.find(1)
678 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
678 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
679 auth_source.account_password = ''
679 auth_source.account_password = ''
680 auth_source.save!
680 auth_source.save!
681
681
682 assert_difference('User.count') do
682 assert_difference('User.count') do
683 assert User.try_to_login('example1', '123456')
683 assert User.try_to_login('example1', '123456')
684 end
684 end
685
685
686 assert_no_difference('User.count') do
686 assert_no_difference('User.count') do
687 assert User.try_to_login('example1', '123456')
687 assert User.try_to_login('example1', '123456')
688 end
688 end
689
689
690 assert_nil User.try_to_login('example1', '11111')
690 assert_nil User.try_to_login('example1', '11111')
691 end
691 end
692
692
693 else
693 else
694 puts "Skipping LDAP tests."
694 puts "Skipping LDAP tests."
695 end
695 end
696
696
697 def test_create_anonymous
697 def test_create_anonymous
698 AnonymousUser.delete_all
698 AnonymousUser.delete_all
699 anon = User.anonymous
699 anon = User.anonymous
700 assert !anon.new_record?
700 assert !anon.new_record?
701 assert_kind_of AnonymousUser, anon
701 assert_kind_of AnonymousUser, anon
702 end
702 end
703
703
704 def test_ensure_single_anonymous_user
704 def test_ensure_single_anonymous_user
705 AnonymousUser.delete_all
705 AnonymousUser.delete_all
706 anon1 = User.anonymous
706 anon1 = User.anonymous
707 assert !anon1.new_record?
707 assert !anon1.new_record?
708 assert_kind_of AnonymousUser, anon1
708 assert_kind_of AnonymousUser, anon1
709 anon2 = AnonymousUser.create(
709 anon2 = AnonymousUser.create(
710 :lastname => 'Anonymous', :firstname => '',
710 :lastname => 'Anonymous', :firstname => '',
711 :login => '', :status => 0)
711 :login => '', :status => 0)
712 assert_equal 1, anon2.errors.count
712 assert_equal 1, anon2.errors.count
713 end
713 end
714
714
715 def test_rss_key
715 def test_rss_key
716 assert_nil @jsmith.rss_token
716 assert_nil @jsmith.rss_token
717 key = @jsmith.rss_key
717 key = @jsmith.rss_key
718 assert_equal 40, key.length
718 assert_equal 40, key.length
719
719
720 @jsmith.reload
720 @jsmith.reload
721 assert_equal key, @jsmith.rss_key
721 assert_equal key, @jsmith.rss_key
722 end
722 end
723
723
724 def test_rss_key_should_not_be_generated_twice
724 def test_rss_key_should_not_be_generated_twice
725 assert_difference 'Token.count', 1 do
725 assert_difference 'Token.count', 1 do
726 key1 = @jsmith.rss_key
726 key1 = @jsmith.rss_key
727 key2 = @jsmith.rss_key
727 key2 = @jsmith.rss_key
728 assert_equal key1, key2
728 assert_equal key1, key2
729 end
729 end
730 end
730 end
731
731
732 def test_api_key_should_not_be_generated_twice
732 def test_api_key_should_not_be_generated_twice
733 assert_difference 'Token.count', 1 do
733 assert_difference 'Token.count', 1 do
734 key1 = @jsmith.api_key
734 key1 = @jsmith.api_key
735 key2 = @jsmith.api_key
735 key2 = @jsmith.api_key
736 assert_equal key1, key2
736 assert_equal key1, key2
737 end
737 end
738 end
738 end
739
739
740 test "#api_key should generate a new one if the user doesn't have one" do
740 test "#api_key should generate a new one if the user doesn't have one" do
741 user = User.generate!(:api_token => nil)
741 user = User.generate!(:api_token => nil)
742 assert_nil user.api_token
742 assert_nil user.api_token
743
743
744 key = user.api_key
744 key = user.api_key
745 assert_equal 40, key.length
745 assert_equal 40, key.length
746 user.reload
746 user.reload
747 assert_equal key, user.api_key
747 assert_equal key, user.api_key
748 end
748 end
749
749
750 test "#api_key should return the existing api token value" do
750 test "#api_key should return the existing api token value" do
751 user = User.generate!
751 user = User.generate!
752 token = Token.create!(:action => 'api')
752 token = Token.create!(:action => 'api')
753 user.api_token = token
753 user.api_token = token
754 assert user.save
754 assert user.save
755
755
756 assert_equal token.value, user.api_key
756 assert_equal token.value, user.api_key
757 end
757 end
758
758
759 test "#find_by_api_key should return nil if no matching key is found" do
759 test "#find_by_api_key should return nil if no matching key is found" do
760 assert_nil User.find_by_api_key('zzzzzzzzz')
760 assert_nil User.find_by_api_key('zzzzzzzzz')
761 end
761 end
762
762
763 test "#find_by_api_key should return nil if the key is found for an inactive user" do
763 test "#find_by_api_key should return nil if the key is found for an inactive user" do
764 user = User.generate!
764 user = User.generate!
765 user.status = User::STATUS_LOCKED
765 user.status = User::STATUS_LOCKED
766 token = Token.create!(:action => 'api')
766 token = Token.create!(:action => 'api')
767 user.api_token = token
767 user.api_token = token
768 user.save
768 user.save
769
769
770 assert_nil User.find_by_api_key(token.value)
770 assert_nil User.find_by_api_key(token.value)
771 end
771 end
772
772
773 test "#find_by_api_key should return the user if the key is found for an active user" do
773 test "#find_by_api_key should return the user if the key is found for an active user" do
774 user = User.generate!
774 user = User.generate!
775 token = Token.create!(:action => 'api')
775 token = Token.create!(:action => 'api')
776 user.api_token = token
776 user.api_token = token
777 user.save
777 user.save
778
778
779 assert_equal user, User.find_by_api_key(token.value)
779 assert_equal user, User.find_by_api_key(token.value)
780 end
780 end
781
781
782 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
782 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
783 user = User.find_by_login("admin")
783 user = User.find_by_login("admin")
784 user.password = "admin"
784 user.password = "admin"
785 assert user.save(:validate => false)
785 assert user.save(:validate => false)
786
786
787 assert_equal false, User.default_admin_account_changed?
787 assert_equal false, User.default_admin_account_changed?
788 end
788 end
789
789
790 def test_default_admin_account_changed_should_return_true_if_password_was_changed
790 def test_default_admin_account_changed_should_return_true_if_password_was_changed
791 user = User.find_by_login("admin")
791 user = User.find_by_login("admin")
792 user.password = "newpassword"
792 user.password = "newpassword"
793 user.save!
793 user.save!
794
794
795 assert_equal true, User.default_admin_account_changed?
795 assert_equal true, User.default_admin_account_changed?
796 end
796 end
797
797
798 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
798 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
799 user = User.find_by_login("admin")
799 user = User.find_by_login("admin")
800 user.password = "admin"
800 user.password = "admin"
801 user.status = User::STATUS_LOCKED
801 user.status = User::STATUS_LOCKED
802 assert user.save(:validate => false)
802 assert user.save(:validate => false)
803
803
804 assert_equal true, User.default_admin_account_changed?
804 assert_equal true, User.default_admin_account_changed?
805 end
805 end
806
806
807 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
807 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
808 user = User.find_by_login("admin")
808 user = User.find_by_login("admin")
809 user.destroy
809 user.destroy
810
810
811 assert_equal true, User.default_admin_account_changed?
811 assert_equal true, User.default_admin_account_changed?
812 end
812 end
813
813
814 def test_membership_with_project_should_return_membership
814 def test_membership_with_project_should_return_membership
815 project = Project.find(1)
815 project = Project.find(1)
816
816
817 membership = @jsmith.membership(project)
817 membership = @jsmith.membership(project)
818 assert_kind_of Member, membership
818 assert_kind_of Member, membership
819 assert_equal @jsmith, membership.user
819 assert_equal @jsmith, membership.user
820 assert_equal project, membership.project
820 assert_equal project, membership.project
821 end
821 end
822
822
823 def test_membership_with_project_id_should_return_membership
823 def test_membership_with_project_id_should_return_membership
824 project = Project.find(1)
824 project = Project.find(1)
825
825
826 membership = @jsmith.membership(1)
826 membership = @jsmith.membership(1)
827 assert_kind_of Member, membership
827 assert_kind_of Member, membership
828 assert_equal @jsmith, membership.user
828 assert_equal @jsmith, membership.user
829 assert_equal project, membership.project
829 assert_equal project, membership.project
830 end
830 end
831
831
832 def test_membership_for_non_member_should_return_nil
832 def test_membership_for_non_member_should_return_nil
833 project = Project.find(1)
833 project = Project.find(1)
834
834
835 user = User.generate!
835 user = User.generate!
836 membership = user.membership(1)
836 membership = user.membership(1)
837 assert_nil membership
837 assert_nil membership
838 end
838 end
839
839
840 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
840 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
841 roles = @jsmith.roles_for_project(Project.find(1))
841 roles = @jsmith.roles_for_project(Project.find(1))
842 assert_kind_of Role, roles.first
842 assert_kind_of Role, roles.first
843 assert_equal ["Manager"], roles.map(&:name)
843 assert_equal ["Manager"], roles.map(&:name)
844 end
844 end
845
845
846 def test_roles_for_project_with_member_on_private_project_should_return_roles
846 def test_roles_for_project_with_member_on_private_project_should_return_roles
847 Project.find(1).update_attribute :is_public, false
847 Project.find(1).update_attribute :is_public, false
848
848
849 roles = @jsmith.roles_for_project(Project.find(1))
849 roles = @jsmith.roles_for_project(Project.find(1))
850 assert_kind_of Role, roles.first
850 assert_kind_of Role, roles.first
851 assert_equal ["Manager"], roles.map(&:name)
851 assert_equal ["Manager"], roles.map(&:name)
852 end
852 end
853
853
854 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
854 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
855 set_language_if_valid 'en'
855 set_language_if_valid 'en'
856 roles = User.find(8).roles_for_project(Project.find(1))
856 roles = User.find(8).roles_for_project(Project.find(1))
857 assert_equal ["Non member"], roles.map(&:name)
857 assert_equal ["Non member"], roles.map(&:name)
858 end
858 end
859
859
860 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
860 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
861 project = Project.find(1)
861 project = Project.find(1)
862 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
862 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
863 roles = User.find(8).roles_for_project(project)
863 roles = User.find(8).roles_for_project(project)
864 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
864 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
865 end
865 end
866
866
867 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
867 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
868 Project.find(1).update_attribute :is_public, false
868 Project.find(1).update_attribute :is_public, false
869
869
870 roles = User.find(8).roles_for_project(Project.find(1))
870 roles = User.find(8).roles_for_project(Project.find(1))
871 assert_equal [], roles.map(&:name)
871 assert_equal [], roles.map(&:name)
872 end
872 end
873
873
874 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
874 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
875 project = Project.find(1)
875 project = Project.find(1)
876 project.update_attribute :is_public, false
876 project.update_attribute :is_public, false
877 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
877 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
878 roles = User.find(8).roles_for_project(project)
878 roles = User.find(8).roles_for_project(project)
879 assert_equal [], roles.map(&:name).sort
879 assert_equal [], roles.map(&:name).sort
880 end
880 end
881
881
882 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
882 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
883 set_language_if_valid 'en'
883 set_language_if_valid 'en'
884 roles = User.anonymous.roles_for_project(Project.find(1))
884 roles = User.anonymous.roles_for_project(Project.find(1))
885 assert_equal ["Anonymous"], roles.map(&:name)
885 assert_equal ["Anonymous"], roles.map(&:name)
886 end
886 end
887
887
888 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
888 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
889 project = Project.find(1)
889 project = Project.find(1)
890 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
890 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
891 roles = User.anonymous.roles_for_project(project)
891 roles = User.anonymous.roles_for_project(project)
892 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
892 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
893 end
893 end
894
894
895 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
895 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
896 Project.find(1).update_attribute :is_public, false
896 Project.find(1).update_attribute :is_public, false
897
897
898 roles = User.anonymous.roles_for_project(Project.find(1))
898 roles = User.anonymous.roles_for_project(Project.find(1))
899 assert_equal [], roles.map(&:name)
899 assert_equal [], roles.map(&:name)
900 end
900 end
901
901
902 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
902 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
903 project = Project.find(1)
903 project = Project.find(1)
904 project.update_attribute :is_public, false
904 project.update_attribute :is_public, false
905 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
905 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
906 roles = User.anonymous.roles_for_project(project)
906 roles = User.anonymous.roles_for_project(project)
907 assert_equal [], roles.map(&:name).sort
907 assert_equal [], roles.map(&:name).sort
908 end
908 end
909
909
910 def test_roles_for_project_should_be_unique
911 m = Member.new(:user_id => 1, :project_id => 1)
912 m.member_roles.build(:role_id => 1)
913 m.member_roles.build(:role_id => 1)
914 m.save!
915
916 user = User.find(1)
917 project = Project.find(1)
918 assert_equal 1, user.roles_for_project(project).size
919 assert_equal [1], user.roles_for_project(project).map(&:id)
920 end
921
910 def test_projects_by_role_for_user_with_role
922 def test_projects_by_role_for_user_with_role
911 user = User.find(2)
923 user = User.find(2)
912 assert_kind_of Hash, user.projects_by_role
924 assert_kind_of Hash, user.projects_by_role
913 assert_equal 2, user.projects_by_role.size
925 assert_equal 2, user.projects_by_role.size
914 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
926 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
915 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
927 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
916 end
928 end
917
929
918 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
930 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
919 user = User.find(2)
931 user = User.find(2)
920 assert_equal [], user.projects_by_role[Role.find(3)]
932 assert_equal [], user.projects_by_role[Role.find(3)]
921 # should not update the hash
933 # should not update the hash
922 assert_nil user.projects_by_role.values.detect(&:blank?)
934 assert_nil user.projects_by_role.values.detect(&:blank?)
923 end
935 end
924
936
925 def test_projects_by_role_for_user_with_no_role
937 def test_projects_by_role_for_user_with_no_role
926 user = User.generate!
938 user = User.generate!
927 assert_equal({}, user.projects_by_role)
939 assert_equal({}, user.projects_by_role)
928 end
940 end
929
941
930 def test_projects_by_role_for_anonymous
942 def test_projects_by_role_for_anonymous
931 assert_equal({}, User.anonymous.projects_by_role)
943 assert_equal({}, User.anonymous.projects_by_role)
932 end
944 end
933
945
934 def test_valid_notification_options
946 def test_valid_notification_options
935 # without memberships
947 # without memberships
936 assert_equal 5, User.find(7).valid_notification_options.size
948 assert_equal 5, User.find(7).valid_notification_options.size
937 # with memberships
949 # with memberships
938 assert_equal 6, User.find(2).valid_notification_options.size
950 assert_equal 6, User.find(2).valid_notification_options.size
939 end
951 end
940
952
941 def test_valid_notification_options_class_method
953 def test_valid_notification_options_class_method
942 assert_equal 5, User.valid_notification_options.size
954 assert_equal 5, User.valid_notification_options.size
943 assert_equal 5, User.valid_notification_options(User.find(7)).size
955 assert_equal 5, User.valid_notification_options(User.find(7)).size
944 assert_equal 6, User.valid_notification_options(User.find(2)).size
956 assert_equal 6, User.valid_notification_options(User.find(2)).size
945 end
957 end
946
958
947 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
959 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
948 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
960 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
949 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
961 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
950 end
962 end
951
963
952 def test_mail_notification_all
964 def test_mail_notification_all
953 @jsmith.mail_notification = 'all'
965 @jsmith.mail_notification = 'all'
954 @jsmith.notified_project_ids = []
966 @jsmith.notified_project_ids = []
955 @jsmith.save
967 @jsmith.save
956 @jsmith.reload
968 @jsmith.reload
957 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
969 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
958 end
970 end
959
971
960 def test_mail_notification_selected
972 def test_mail_notification_selected
961 @jsmith.mail_notification = 'selected'
973 @jsmith.mail_notification = 'selected'
962 @jsmith.notified_project_ids = [1]
974 @jsmith.notified_project_ids = [1]
963 @jsmith.save
975 @jsmith.save
964 @jsmith.reload
976 @jsmith.reload
965 assert Project.find(1).recipients.include?(@jsmith.mail)
977 assert Project.find(1).recipients.include?(@jsmith.mail)
966 end
978 end
967
979
968 def test_mail_notification_only_my_events
980 def test_mail_notification_only_my_events
969 @jsmith.mail_notification = 'only_my_events'
981 @jsmith.mail_notification = 'only_my_events'
970 @jsmith.notified_project_ids = []
982 @jsmith.notified_project_ids = []
971 @jsmith.save
983 @jsmith.save
972 @jsmith.reload
984 @jsmith.reload
973 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
985 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
974 end
986 end
975
987
976 def test_comments_sorting_preference
988 def test_comments_sorting_preference
977 assert !@jsmith.wants_comments_in_reverse_order?
989 assert !@jsmith.wants_comments_in_reverse_order?
978 @jsmith.pref.comments_sorting = 'asc'
990 @jsmith.pref.comments_sorting = 'asc'
979 assert !@jsmith.wants_comments_in_reverse_order?
991 assert !@jsmith.wants_comments_in_reverse_order?
980 @jsmith.pref.comments_sorting = 'desc'
992 @jsmith.pref.comments_sorting = 'desc'
981 assert @jsmith.wants_comments_in_reverse_order?
993 assert @jsmith.wants_comments_in_reverse_order?
982 end
994 end
983
995
984 def test_find_by_mail_should_be_case_insensitive
996 def test_find_by_mail_should_be_case_insensitive
985 u = User.find_by_mail('JSmith@somenet.foo')
997 u = User.find_by_mail('JSmith@somenet.foo')
986 assert_not_nil u
998 assert_not_nil u
987 assert_equal 'jsmith@somenet.foo', u.mail
999 assert_equal 'jsmith@somenet.foo', u.mail
988 end
1000 end
989
1001
990 def test_random_password
1002 def test_random_password
991 u = User.new
1003 u = User.new
992 u.random_password
1004 u.random_password
993 assert !u.password.blank?
1005 assert !u.password.blank?
994 assert !u.password_confirmation.blank?
1006 assert !u.password_confirmation.blank?
995 end
1007 end
996
1008
997 test "#change_password_allowed? should be allowed if no auth source is set" do
1009 test "#change_password_allowed? should be allowed if no auth source is set" do
998 user = User.generate!
1010 user = User.generate!
999 assert user.change_password_allowed?
1011 assert user.change_password_allowed?
1000 end
1012 end
1001
1013
1002 test "#change_password_allowed? should delegate to the auth source" do
1014 test "#change_password_allowed? should delegate to the auth source" do
1003 user = User.generate!
1015 user = User.generate!
1004
1016
1005 allowed_auth_source = AuthSource.generate!
1017 allowed_auth_source = AuthSource.generate!
1006 def allowed_auth_source.allow_password_changes?; true; end
1018 def allowed_auth_source.allow_password_changes?; true; end
1007
1019
1008 denied_auth_source = AuthSource.generate!
1020 denied_auth_source = AuthSource.generate!
1009 def denied_auth_source.allow_password_changes?; false; end
1021 def denied_auth_source.allow_password_changes?; false; end
1010
1022
1011 assert user.change_password_allowed?
1023 assert user.change_password_allowed?
1012
1024
1013 user.auth_source = allowed_auth_source
1025 user.auth_source = allowed_auth_source
1014 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1026 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1015
1027
1016 user.auth_source = denied_auth_source
1028 user.auth_source = denied_auth_source
1017 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1029 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1018 end
1030 end
1019
1031
1020 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1032 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1021 with_settings :unsubscribe => '1' do
1033 with_settings :unsubscribe => '1' do
1022 assert_equal true, User.find(2).own_account_deletable?
1034 assert_equal true, User.find(2).own_account_deletable?
1023 end
1035 end
1024 end
1036 end
1025
1037
1026 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1038 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1027 with_settings :unsubscribe => '0' do
1039 with_settings :unsubscribe => '0' do
1028 assert_equal false, User.find(2).own_account_deletable?
1040 assert_equal false, User.find(2).own_account_deletable?
1029 end
1041 end
1030 end
1042 end
1031
1043
1032 def test_own_account_deletable_should_be_false_for_a_single_admin
1044 def test_own_account_deletable_should_be_false_for_a_single_admin
1033 User.delete_all(["admin = ? AND id <> ?", true, 1])
1045 User.delete_all(["admin = ? AND id <> ?", true, 1])
1034
1046
1035 with_settings :unsubscribe => '1' do
1047 with_settings :unsubscribe => '1' do
1036 assert_equal false, User.find(1).own_account_deletable?
1048 assert_equal false, User.find(1).own_account_deletable?
1037 end
1049 end
1038 end
1050 end
1039
1051
1040 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1052 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1041 User.generate! do |user|
1053 User.generate! do |user|
1042 user.admin = true
1054 user.admin = true
1043 end
1055 end
1044
1056
1045 with_settings :unsubscribe => '1' do
1057 with_settings :unsubscribe => '1' do
1046 assert_equal true, User.find(1).own_account_deletable?
1058 assert_equal true, User.find(1).own_account_deletable?
1047 end
1059 end
1048 end
1060 end
1049
1061
1050 test "#allowed_to? for archived project should return false" do
1062 test "#allowed_to? for archived project should return false" do
1051 project = Project.find(1)
1063 project = Project.find(1)
1052 project.archive
1064 project.archive
1053 project.reload
1065 project.reload
1054 assert_equal false, @admin.allowed_to?(:view_issues, project)
1066 assert_equal false, @admin.allowed_to?(:view_issues, project)
1055 end
1067 end
1056
1068
1057 test "#allowed_to? for closed project should return true for read actions" do
1069 test "#allowed_to? for closed project should return true for read actions" do
1058 project = Project.find(1)
1070 project = Project.find(1)
1059 project.close
1071 project.close
1060 project.reload
1072 project.reload
1061 assert_equal false, @admin.allowed_to?(:edit_project, project)
1073 assert_equal false, @admin.allowed_to?(:edit_project, project)
1062 assert_equal true, @admin.allowed_to?(:view_project, project)
1074 assert_equal true, @admin.allowed_to?(:view_project, project)
1063 end
1075 end
1064
1076
1065 test "#allowed_to? for project with module disabled should return false" do
1077 test "#allowed_to? for project with module disabled should return false" do
1066 project = Project.find(1)
1078 project = Project.find(1)
1067 project.enabled_module_names = ["issue_tracking"]
1079 project.enabled_module_names = ["issue_tracking"]
1068 assert_equal true, @admin.allowed_to?(:add_issues, project)
1080 assert_equal true, @admin.allowed_to?(:add_issues, project)
1069 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1081 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1070 end
1082 end
1071
1083
1072 test "#allowed_to? for admin users should return true" do
1084 test "#allowed_to? for admin users should return true" do
1073 project = Project.find(1)
1085 project = Project.find(1)
1074 assert ! @admin.member_of?(project)
1086 assert ! @admin.member_of?(project)
1075 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1087 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1076 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1088 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1077 end
1089 end
1078 end
1090 end
1079
1091
1080 test "#allowed_to? for normal users" do
1092 test "#allowed_to? for normal users" do
1081 project = Project.find(1)
1093 project = Project.find(1)
1082 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1094 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1083 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1095 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1084 end
1096 end
1085
1097
1086 test "#allowed_to? with empty array should return false" do
1098 test "#allowed_to? with empty array should return false" do
1087 assert_equal false, @admin.allowed_to?(:view_project, [])
1099 assert_equal false, @admin.allowed_to?(:view_project, [])
1088 end
1100 end
1089
1101
1090 test "#allowed_to? with multiple projects" do
1102 test "#allowed_to? with multiple projects" do
1091 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1103 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1092 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1104 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1093 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1105 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1094 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1106 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1095 end
1107 end
1096
1108
1097 test "#allowed_to? with with options[:global] should return true if user has one role with the permission" do
1109 test "#allowed_to? with with options[:global] should return true if user has one role with the permission" do
1098 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1110 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1099 @anonymous = User.find(6)
1111 @anonymous = User.find(6)
1100 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1112 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1101 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1113 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1102 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1114 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1103 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1115 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1104 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1116 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1105 end
1117 end
1106
1118
1107 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1119 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1108 test "#allowed_to_globally?" do
1120 test "#allowed_to_globally?" do
1109 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1121 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1110 @anonymous = User.find(6)
1122 @anonymous = User.find(6)
1111 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1123 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1112 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1124 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1113 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1125 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1114 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1126 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1115 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1127 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1116 end
1128 end
1117
1129
1118 def test_notify_about_issue
1130 def test_notify_about_issue
1119 project = Project.find(1)
1131 project = Project.find(1)
1120 author = User.generate!
1132 author = User.generate!
1121 assignee = User.generate!
1133 assignee = User.generate!
1122 member = User.generate!
1134 member = User.generate!
1123 Member.create!(:user => member, :project => project, :role_ids => [1])
1135 Member.create!(:user => member, :project => project, :role_ids => [1])
1124 issue = Issue.generate!(:project => project, :assigned_to => assignee, :author => author)
1136 issue = Issue.generate!(:project => project, :assigned_to => assignee, :author => author)
1125
1137
1126 tests = {
1138 tests = {
1127 author => %w(all only_my_events only_owner selected),
1139 author => %w(all only_my_events only_owner selected),
1128 assignee => %w(all only_my_events only_assigned selected),
1140 assignee => %w(all only_my_events only_assigned selected),
1129 member => %w(all)
1141 member => %w(all)
1130 }
1142 }
1131
1143
1132 tests.each do |user, expected|
1144 tests.each do |user, expected|
1133 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1145 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1134 user.mail_notification = option
1146 user.mail_notification = option
1135 assert_equal expected.include?(option), user.notify_about?(issue)
1147 assert_equal expected.include?(option), user.notify_about?(issue)
1136 end
1148 end
1137 end
1149 end
1138 end
1150 end
1139
1151
1140 def test_notify_about_issue_for_previous_assignee
1152 def test_notify_about_issue_for_previous_assignee
1141 assignee = User.generate!(:mail_notification => 'only_assigned')
1153 assignee = User.generate!(:mail_notification => 'only_assigned')
1142 new_assignee = User.generate!(:mail_notification => 'only_assigned')
1154 new_assignee = User.generate!(:mail_notification => 'only_assigned')
1143 issue = Issue.generate!(:assigned_to => assignee)
1155 issue = Issue.generate!(:assigned_to => assignee)
1144
1156
1145 assert assignee.notify_about?(issue)
1157 assert assignee.notify_about?(issue)
1146 assert !new_assignee.notify_about?(issue)
1158 assert !new_assignee.notify_about?(issue)
1147
1159
1148 issue.assigned_to = new_assignee
1160 issue.assigned_to = new_assignee
1149 assert assignee.notify_about?(issue)
1161 assert assignee.notify_about?(issue)
1150 assert new_assignee.notify_about?(issue)
1162 assert new_assignee.notify_about?(issue)
1151
1163
1152 issue.save!
1164 issue.save!
1153 assert !assignee.notify_about?(issue)
1165 assert !assignee.notify_about?(issue)
1154 assert new_assignee.notify_about?(issue)
1166 assert new_assignee.notify_about?(issue)
1155 end
1167 end
1156
1168
1157 def test_notify_about_news
1169 def test_notify_about_news
1158 user = User.generate!
1170 user = User.generate!
1159 news = News.new
1171 news = News.new
1160
1172
1161 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1173 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1162 user.mail_notification = option
1174 user.mail_notification = option
1163 assert_equal (option != 'none'), user.notify_about?(news)
1175 assert_equal (option != 'none'), user.notify_about?(news)
1164 end
1176 end
1165 end
1177 end
1166
1178
1167 def test_salt_unsalted_passwords
1179 def test_salt_unsalted_passwords
1168 # Restore a user with an unsalted password
1180 # Restore a user with an unsalted password
1169 user = User.find(1)
1181 user = User.find(1)
1170 user.salt = nil
1182 user.salt = nil
1171 user.hashed_password = User.hash_password("unsalted")
1183 user.hashed_password = User.hash_password("unsalted")
1172 user.save!
1184 user.save!
1173
1185
1174 User.salt_unsalted_passwords!
1186 User.salt_unsalted_passwords!
1175
1187
1176 user.reload
1188 user.reload
1177 # Salt added
1189 # Salt added
1178 assert !user.salt.blank?
1190 assert !user.salt.blank?
1179 # Password still valid
1191 # Password still valid
1180 assert user.check_password?("unsalted")
1192 assert user.check_password?("unsalted")
1181 assert_equal user, User.try_to_login(user.login, "unsalted")
1193 assert_equal user, User.try_to_login(user.login, "unsalted")
1182 end
1194 end
1183
1195
1184 if Object.const_defined?(:OpenID)
1196 if Object.const_defined?(:OpenID)
1185 def test_setting_identity_url
1197 def test_setting_identity_url
1186 normalized_open_id_url = 'http://example.com/'
1198 normalized_open_id_url = 'http://example.com/'
1187 u = User.new( :identity_url => 'http://example.com/' )
1199 u = User.new( :identity_url => 'http://example.com/' )
1188 assert_equal normalized_open_id_url, u.identity_url
1200 assert_equal normalized_open_id_url, u.identity_url
1189 end
1201 end
1190
1202
1191 def test_setting_identity_url_without_trailing_slash
1203 def test_setting_identity_url_without_trailing_slash
1192 normalized_open_id_url = 'http://example.com/'
1204 normalized_open_id_url = 'http://example.com/'
1193 u = User.new( :identity_url => 'http://example.com' )
1205 u = User.new( :identity_url => 'http://example.com' )
1194 assert_equal normalized_open_id_url, u.identity_url
1206 assert_equal normalized_open_id_url, u.identity_url
1195 end
1207 end
1196
1208
1197 def test_setting_identity_url_without_protocol
1209 def test_setting_identity_url_without_protocol
1198 normalized_open_id_url = 'http://example.com/'
1210 normalized_open_id_url = 'http://example.com/'
1199 u = User.new( :identity_url => 'example.com' )
1211 u = User.new( :identity_url => 'example.com' )
1200 assert_equal normalized_open_id_url, u.identity_url
1212 assert_equal normalized_open_id_url, u.identity_url
1201 end
1213 end
1202
1214
1203 def test_setting_blank_identity_url
1215 def test_setting_blank_identity_url
1204 u = User.new( :identity_url => 'example.com' )
1216 u = User.new( :identity_url => 'example.com' )
1205 u.identity_url = ''
1217 u.identity_url = ''
1206 assert u.identity_url.blank?
1218 assert u.identity_url.blank?
1207 end
1219 end
1208
1220
1209 def test_setting_invalid_identity_url
1221 def test_setting_invalid_identity_url
1210 u = User.new( :identity_url => 'this is not an openid url' )
1222 u = User.new( :identity_url => 'this is not an openid url' )
1211 assert u.identity_url.blank?
1223 assert u.identity_url.blank?
1212 end
1224 end
1213 else
1225 else
1214 puts "Skipping openid tests."
1226 puts "Skipping openid tests."
1215 end
1227 end
1216 end
1228 end
General Comments 0
You need to be logged in to leave comments. Login now