comparison test/unit/issue_test.rb @ 441:cbce1fd3b1b7 redmine-1.2

Update to Redmine 1.2-stable branch (Redmine SVN rev 6000)
author Chris Cannam
date Mon, 06 Jun 2011 14:24:13 +0100
parents 051f544170fe
children 0c939c159af4
comparison
equal deleted inserted replaced
245:051f544170fe 441:cbce1fd3b1b7
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__)
20 class IssueTest < ActiveSupport::TestCase 20 class IssueTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :members, :member_roles, :roles, 21 fixtures :projects, :users, :members, :member_roles, :roles,
22 :trackers, :projects_trackers, 22 :trackers, :projects_trackers,
23 :enabled_modules, 23 :enabled_modules,
24 :versions, 24 :versions,
25 :issue_statuses, :issue_categories, :issue_relations, :workflows, 25 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :enumerations, 26 :enumerations,
27 :issues, 27 :issues,
28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values, 28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :time_entries 29 :time_entries
30 30
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :description => 'IssueTest#test_create', :estimated_hours => '1:30') 32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :description => 'IssueTest#test_create', :estimated_hours => '1:30')
33 assert issue.save 33 assert issue.save
34 issue.reload 34 issue.reload
35 assert_equal 1.5, issue.estimated_hours 35 assert_equal 1.5, issue.estimated_hours
36 end 36 end
37 37
38 def test_create_minimal 38 def test_create_minimal
39 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create') 39 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create')
40 assert issue.save 40 assert issue.save
41 assert issue.description.nil? 41 assert issue.description.nil?
42 end 42 end
43 43
44 def test_create_with_required_custom_field 44 def test_create_with_required_custom_field
45 field = IssueCustomField.find_by_name('Database') 45 field = IssueCustomField.find_by_name('Database')
46 field.update_attribute(:is_required, true) 46 field.update_attribute(:is_required, true)
47 47
48 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field') 48 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field')
49 assert issue.available_custom_fields.include?(field) 49 assert issue.available_custom_fields.include?(field)
50 # No value for the custom field 50 # No value for the custom field
51 assert !issue.save 51 assert !issue.save
52 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values) 52 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
62 issue.custom_field_values = { field.id => 'PostgreSQL' } 62 issue.custom_field_values = { field.id => 'PostgreSQL' }
63 assert issue.save 63 assert issue.save
64 issue.reload 64 issue.reload
65 assert_equal 'PostgreSQL', issue.custom_value_for(field).value 65 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
66 end 66 end
67 67
68 def assert_visibility_match(user, issues)
69 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
70 end
71
68 def test_visible_scope_for_anonymous 72 def test_visible_scope_for_anonymous
69 # Anonymous user should see issues of public projects only 73 # Anonymous user should see issues of public projects only
70 issues = Issue.visible(User.anonymous).all 74 issues = Issue.visible(User.anonymous).all
71 assert issues.any? 75 assert issues.any?
72 assert_nil issues.detect {|issue| !issue.project.is_public?} 76 assert_nil issues.detect {|issue| !issue.project.is_public?}
77 assert_nil issues.detect {|issue| issue.is_private?}
78 assert_visibility_match User.anonymous, issues
79 end
80
81 def test_visible_scope_for_anonymous_with_own_issues_visibility
82 Role.anonymous.update_attribute :issues_visibility, 'own'
83 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => User.anonymous.id, :subject => 'Issue by anonymous')
84
85 issues = Issue.visible(User.anonymous).all
86 assert issues.any?
87 assert_nil issues.detect {|issue| issue.author != User.anonymous}
88 assert_visibility_match User.anonymous, issues
89 end
90
91 def test_visible_scope_for_anonymous_without_view_issues_permissions
73 # Anonymous user should not see issues without permission 92 # Anonymous user should not see issues without permission
74 Role.anonymous.remove_permission!(:view_issues) 93 Role.anonymous.remove_permission!(:view_issues)
75 issues = Issue.visible(User.anonymous).all 94 issues = Issue.visible(User.anonymous).all
76 assert issues.empty? 95 assert issues.empty?
77 end 96 assert_visibility_match User.anonymous, issues
78 97 end
79 def test_visible_scope_for_user 98
99 def test_visible_scope_for_non_member
80 user = User.find(9) 100 user = User.find(9)
81 assert user.projects.empty? 101 assert user.projects.empty?
82 # Non member user should see issues of public projects only 102 # Non member user should see issues of public projects only
83 issues = Issue.visible(user).all 103 issues = Issue.visible(user).all
84 assert issues.any? 104 assert issues.any?
85 assert_nil issues.detect {|issue| !issue.project.is_public?} 105 assert_nil issues.detect {|issue| !issue.project.is_public?}
106 assert_nil issues.detect {|issue| issue.is_private?}
107 assert_visibility_match user, issues
108 end
109
110 def test_visible_scope_for_non_member_with_own_issues_visibility
111 Role.non_member.update_attribute :issues_visibility, 'own'
112 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
113 user = User.find(9)
114
115 issues = Issue.visible(user).all
116 assert issues.any?
117 assert_nil issues.detect {|issue| issue.author != user}
118 assert_visibility_match user, issues
119 end
120
121 def test_visible_scope_for_non_member_without_view_issues_permissions
86 # Non member user should not see issues without permission 122 # Non member user should not see issues without permission
87 Role.non_member.remove_permission!(:view_issues) 123 Role.non_member.remove_permission!(:view_issues)
88 user.reload 124 user = User.find(9)
125 assert user.projects.empty?
89 issues = Issue.visible(user).all 126 issues = Issue.visible(user).all
90 assert issues.empty? 127 assert issues.empty?
128 assert_visibility_match user, issues
129 end
130
131 def test_visible_scope_for_member
132 user = User.find(9)
91 # User should see issues of projects for which he has view_issues permissions only 133 # User should see issues of projects for which he has view_issues permissions only
92 Member.create!(:principal => user, :project_id => 2, :role_ids => [1]) 134 Role.non_member.remove_permission!(:view_issues)
93 user.reload 135 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
94 issues = Issue.visible(user).all 136 issues = Issue.visible(user).all
95 assert issues.any? 137 assert issues.any?
96 assert_nil issues.detect {|issue| issue.project_id != 2} 138 assert_nil issues.detect {|issue| issue.project_id != 3}
97 end 139 assert_nil issues.detect {|issue| issue.is_private?}
98 140 assert_visibility_match user, issues
141 end
142
99 def test_visible_scope_for_admin 143 def test_visible_scope_for_admin
100 user = User.find(1) 144 user = User.find(1)
101 user.members.each(&:destroy) 145 user.members.each(&:destroy)
102 assert user.projects.empty? 146 assert user.projects.empty?
103 issues = Issue.visible(user).all 147 issues = Issue.visible(user).all
104 assert issues.any? 148 assert issues.any?
105 # Admin should see issues on private projects that he does not belong to 149 # Admin should see issues on private projects that he does not belong to
106 assert issues.detect {|issue| !issue.project.is_public?} 150 assert issues.detect {|issue| !issue.project.is_public?}
107 end 151 # Admin should see private issues of other users
108 152 assert issues.detect {|issue| issue.is_private? && issue.author != user}
153 assert_visibility_match user, issues
154 end
155
156 def test_visible_scope_with_project
157 project = Project.find(1)
158 issues = Issue.visible(User.find(2), :project => project).all
159 projects = issues.collect(&:project).uniq
160 assert_equal 1, projects.size
161 assert_equal project, projects.first
162 end
163
164 def test_visible_scope_with_project_and_subprojects
165 project = Project.find(1)
166 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
167 projects = issues.collect(&:project).uniq
168 assert projects.size > 1
169 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
170 end
171
172 def test_visible_and_nested_set_scopes
173 assert_equal 0, Issue.find(1).descendants.visible.all.size
174 end
175
109 def test_errors_full_messages_should_include_custom_fields_errors 176 def test_errors_full_messages_should_include_custom_fields_errors
110 field = IssueCustomField.find_by_name('Database') 177 field = IssueCustomField.find_by_name('Database')
111 178
112 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field') 179 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field')
113 assert issue.available_custom_fields.include?(field) 180 assert issue.available_custom_fields.include?(field)
114 # Invalid value 181 # Invalid value
115 issue.custom_field_values = { field.id => 'SQLServer' } 182 issue.custom_field_values = { field.id => 'SQLServer' }
116 183
117 assert !issue.valid? 184 assert !issue.valid?
118 assert_equal 1, issue.errors.full_messages.size 185 assert_equal 1, issue.errors.full_messages.size
119 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", issue.errors.full_messages.first 186 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", issue.errors.full_messages.first
120 end 187 end
121 188
122 def test_update_issue_with_required_custom_field 189 def test_update_issue_with_required_custom_field
123 field = IssueCustomField.find_by_name('Database') 190 field = IssueCustomField.find_by_name('Database')
124 field.update_attribute(:is_required, true) 191 field.update_attribute(:is_required, true)
125 192
126 issue = Issue.find(1) 193 issue = Issue.find(1)
127 assert_nil issue.custom_value_for(field) 194 assert_nil issue.custom_value_for(field)
128 assert issue.available_custom_fields.include?(field) 195 assert issue.available_custom_fields.include?(field)
129 # No change to custom values, issue can be saved 196 # No change to custom values, issue can be saved
130 assert issue.save 197 assert issue.save
135 issue.custom_field_values = { field.id => 'PostgreSQL' } 202 issue.custom_field_values = { field.id => 'PostgreSQL' }
136 assert issue.save 203 assert issue.save
137 issue.reload 204 issue.reload
138 assert_equal 'PostgreSQL', issue.custom_value_for(field).value 205 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
139 end 206 end
140 207
141 def test_should_not_update_attributes_if_custom_fields_validation_fails 208 def test_should_not_update_attributes_if_custom_fields_validation_fails
142 issue = Issue.find(1) 209 issue = Issue.find(1)
143 field = IssueCustomField.find_by_name('Database') 210 field = IssueCustomField.find_by_name('Database')
144 assert issue.available_custom_fields.include?(field) 211 assert issue.available_custom_fields.include?(field)
145 212
146 issue.custom_field_values = { field.id => 'Invalid' } 213 issue.custom_field_values = { field.id => 'Invalid' }
147 issue.subject = 'Should be not be saved' 214 issue.subject = 'Should be not be saved'
148 assert !issue.save 215 assert !issue.save
149 216
150 issue.reload 217 issue.reload
151 assert_equal "Can't print recipes", issue.subject 218 assert_equal "Can't print recipes", issue.subject
152 end 219 end
153 220
154 def test_should_not_recreate_custom_values_objects_on_update 221 def test_should_not_recreate_custom_values_objects_on_update
155 field = IssueCustomField.find_by_name('Database') 222 field = IssueCustomField.find_by_name('Database')
156 223
157 issue = Issue.find(1) 224 issue = Issue.find(1)
158 issue.custom_field_values = { field.id => 'PostgreSQL' } 225 issue.custom_field_values = { field.id => 'PostgreSQL' }
159 assert issue.save 226 assert issue.save
160 custom_value = issue.custom_value_for(field) 227 custom_value = issue.custom_value_for(field)
161 issue.reload 228 issue.reload
162 issue.custom_field_values = { field.id => 'MySQL' } 229 issue.custom_field_values = { field.id => 'MySQL' }
163 assert issue.save 230 assert issue.save
164 issue.reload 231 issue.reload
165 assert_equal custom_value.id, issue.custom_value_for(field).id 232 assert_equal custom_value.id, issue.custom_value_for(field).id
166 end 233 end
167 234
168 def test_assigning_tracker_id_should_reload_custom_fields_values 235 def test_assigning_tracker_id_should_reload_custom_fields_values
169 issue = Issue.new(:project => Project.find(1)) 236 issue = Issue.new(:project => Project.find(1))
170 assert issue.custom_field_values.empty? 237 assert issue.custom_field_values.empty?
171 issue.tracker_id = 1 238 issue.tracker_id = 1
172 assert issue.custom_field_values.any? 239 assert issue.custom_field_values.any?
173 end 240 end
174 241
175 def test_assigning_attributes_should_assign_tracker_id_first 242 def test_assigning_attributes_should_assign_tracker_id_first
176 attributes = ActiveSupport::OrderedHash.new 243 attributes = ActiveSupport::OrderedHash.new
177 attributes['custom_field_values'] = { '1' => 'MySQL' } 244 attributes['custom_field_values'] = { '1' => 'MySQL' }
178 attributes['tracker_id'] = '1' 245 attributes['tracker_id'] = '1'
179 issue = Issue.new(:project => Project.find(1)) 246 issue = Issue.new(:project => Project.find(1))
180 issue.attributes = attributes 247 issue.attributes = attributes
181 assert_not_nil issue.custom_value_for(1) 248 assert_not_nil issue.custom_value_for(1)
182 assert_equal 'MySQL', issue.custom_value_for(1).value 249 assert_equal 'MySQL', issue.custom_value_for(1).value
183 end 250 end
184 251
185 def test_should_update_issue_with_disabled_tracker 252 def test_should_update_issue_with_disabled_tracker
186 p = Project.find(1) 253 p = Project.find(1)
187 issue = Issue.find(1) 254 issue = Issue.find(1)
188 255
189 p.trackers.delete(issue.tracker) 256 p.trackers.delete(issue.tracker)
190 assert !p.trackers.include?(issue.tracker) 257 assert !p.trackers.include?(issue.tracker)
191 258
192 issue.reload 259 issue.reload
193 issue.subject = 'New subject' 260 issue.subject = 'New subject'
194 assert issue.save 261 assert issue.save
195 end 262 end
196 263
197 def test_should_not_set_a_disabled_tracker 264 def test_should_not_set_a_disabled_tracker
198 p = Project.find(1) 265 p = Project.find(1)
199 p.trackers.delete(Tracker.find(2)) 266 p.trackers.delete(Tracker.find(2))
200 267
201 issue = Issue.find(1) 268 issue = Issue.find(1)
202 issue.tracker_id = 2 269 issue.tracker_id = 2
203 issue.subject = 'New subject' 270 issue.subject = 'New subject'
204 assert !issue.save 271 assert !issue.save
205 assert_not_nil issue.errors.on(:tracker_id) 272 assert_not_nil issue.errors.on(:tracker_id)
206 end 273 end
207 274
208 def test_category_based_assignment 275 def test_category_based_assignment
209 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1) 276 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1)
210 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to 277 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
211 end 278 end
212 279
213
214
215 def test_new_statuses_allowed_to 280 def test_new_statuses_allowed_to
216 Workflow.delete_all 281 Workflow.delete_all
217 282
218 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false) 283 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
219 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false) 284 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
220 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true) 285 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
221 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true) 286 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
222 status = IssueStatus.find(1) 287 status = IssueStatus.find(1)
223 role = Role.find(1) 288 role = Role.find(1)
224 tracker = Tracker.find(1) 289 tracker = Tracker.find(1)
225 user = User.find(2) 290 user = User.find(2)
226 291
227 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1) 292 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
228 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id) 293 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
229 294
230 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user) 295 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
231 assert_equal [1, 2, 3], issue.new_statuses_allowed_to(user).map(&:id) 296 assert_equal [1, 2, 3], issue.new_statuses_allowed_to(user).map(&:id)
232 297
233 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user) 298 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
234 assert_equal [1, 2, 4], issue.new_statuses_allowed_to(user).map(&:id) 299 assert_equal [1, 2, 4], issue.new_statuses_allowed_to(user).map(&:id)
235 300
236 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user) 301 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
237 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) 302 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
238 end 303 end
239 304
240 def test_copy 305 def test_copy
241 issue = Issue.new.copy_from(1) 306 issue = Issue.new.copy_from(1)
242 assert issue.save 307 assert issue.save
243 issue.reload 308 issue.reload
244 orig = Issue.find(1) 309 orig = Issue.find(1)
248 end 313 end
249 314
250 def test_copy_should_copy_status 315 def test_copy_should_copy_status
251 orig = Issue.find(8) 316 orig = Issue.find(8)
252 assert orig.status != IssueStatus.default 317 assert orig.status != IssueStatus.default
253 318
254 issue = Issue.new.copy_from(orig) 319 issue = Issue.new.copy_from(orig)
255 assert issue.save 320 assert issue.save
256 issue.reload 321 issue.reload
257 assert_equal orig.status, issue.status 322 assert_equal orig.status, issue.status
258 end 323 end
259 324
260 def test_should_close_duplicates 325 def test_should_close_duplicates
261 # Create 3 issues 326 # Create 3 issues
262 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test') 327 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
263 assert issue1.save 328 assert issue1.save
264 issue2 = issue1.clone 329 issue2 = issue1.clone
265 assert issue2.save 330 assert issue2.save
266 issue3 = issue1.clone 331 issue3 = issue1.clone
267 assert issue3.save 332 assert issue3.save
268 333
269 # 2 is a dupe of 1 334 # 2 is a dupe of 1
270 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES) 335 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
271 # And 3 is a dupe of 2 336 # And 3 is a dupe of 2
272 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES) 337 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
273 # And 3 is a dupe of 1 (circular duplicates) 338 # And 3 is a dupe of 1 (circular duplicates)
274 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES) 339 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
275 340
276 assert issue1.reload.duplicates.include?(issue2) 341 assert issue1.reload.duplicates.include?(issue2)
277 342
278 # Closing issue 1 343 # Closing issue 1
279 issue1.init_journal(User.find(:first), "Closing issue1") 344 issue1.init_journal(User.find(:first), "Closing issue1")
280 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true} 345 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
281 assert issue1.save 346 assert issue1.save
282 # 2 and 3 should be also closed 347 # 2 and 3 should be also closed
283 assert issue2.reload.closed? 348 assert issue2.reload.closed?
284 assert issue3.reload.closed? 349 assert issue3.reload.closed?
285 end 350 end
286 351
287 def test_should_not_close_duplicated_issue 352 def test_should_not_close_duplicated_issue
288 # Create 3 issues 353 # Create 3 issues
289 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test') 354 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
290 assert issue1.save 355 assert issue1.save
291 issue2 = issue1.clone 356 issue2 = issue1.clone
292 assert issue2.save 357 assert issue2.save
293 358
294 # 2 is a dupe of 1 359 # 2 is a dupe of 1
295 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES) 360 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
296 # 2 is a dup of 1 but 1 is not a duplicate of 2 361 # 2 is a dup of 1 but 1 is not a duplicate of 2
297 assert !issue2.reload.duplicates.include?(issue1) 362 assert !issue2.reload.duplicates.include?(issue1)
298 363
299 # Closing issue 2 364 # Closing issue 2
300 issue2.init_journal(User.find(:first), "Closing issue2") 365 issue2.init_journal(User.find(:first), "Closing issue2")
301 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true} 366 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
302 assert issue2.save 367 assert issue2.save
303 # 1 should not be also closed 368 # 1 should not be also closed
304 assert !issue1.reload.closed? 369 assert !issue1.reload.closed?
305 end 370 end
306 371
307 def test_assignable_versions 372 def test_assignable_versions
308 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue') 373 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
309 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq 374 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
310 end 375 end
311 376
312 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version 377 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
313 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue') 378 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
314 assert !issue.save 379 assert !issue.save
315 assert_not_nil issue.errors.on(:fixed_version_id) 380 assert_not_nil issue.errors.on(:fixed_version_id)
316 end 381 end
317 382
318 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version 383 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
319 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue') 384 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
320 assert !issue.save 385 assert !issue.save
321 assert_not_nil issue.errors.on(:fixed_version_id) 386 assert_not_nil issue.errors.on(:fixed_version_id)
322 end 387 end
323 388
324 def test_should_be_able_to_assign_a_new_issue_to_an_open_version 389 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
325 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue') 390 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
326 assert issue.save 391 assert issue.save
327 end 392 end
328 393
329 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version 394 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
330 issue = Issue.find(11) 395 issue = Issue.find(11)
331 assert_equal 'closed', issue.fixed_version.status 396 assert_equal 'closed', issue.fixed_version.status
332 issue.subject = 'Subject changed' 397 issue.subject = 'Subject changed'
333 assert issue.save 398 assert issue.save
334 end 399 end
335 400
336 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version 401 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
337 issue = Issue.find(11) 402 issue = Issue.find(11)
338 issue.status_id = 1 403 issue.status_id = 1
339 assert !issue.save 404 assert !issue.save
340 assert_not_nil issue.errors.on_base 405 assert_not_nil issue.errors.on_base
341 end 406 end
342 407
343 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version 408 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
344 issue = Issue.find(11) 409 issue = Issue.find(11)
345 issue.status_id = 1 410 issue.status_id = 1
346 issue.fixed_version_id = 3 411 issue.fixed_version_id = 3
347 assert issue.save 412 assert issue.save
348 end 413 end
349 414
350 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version 415 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
351 issue = Issue.find(12) 416 issue = Issue.find(12)
352 assert_equal 'locked', issue.fixed_version.status 417 assert_equal 'locked', issue.fixed_version.status
353 issue.status_id = 1 418 issue.status_id = 1
354 assert issue.save 419 assert issue.save
355 end 420 end
356 421
357 def test_move_to_another_project_with_same_category 422 def test_move_to_another_project_with_same_category
358 issue = Issue.find(1) 423 issue = Issue.find(1)
359 assert issue.move_to_project(Project.find(2)) 424 assert issue.move_to_project(Project.find(2))
360 issue.reload 425 issue.reload
361 assert_equal 2, issue.project_id 426 assert_equal 2, issue.project_id
362 # Category changes 427 # Category changes
363 assert_equal 4, issue.category_id 428 assert_equal 4, issue.category_id
364 # Make sure time entries were move to the target project 429 # Make sure time entries were move to the target project
365 assert_equal 2, issue.time_entries.first.project_id 430 assert_equal 2, issue.time_entries.first.project_id
366 end 431 end
367 432
368 def test_move_to_another_project_without_same_category 433 def test_move_to_another_project_without_same_category
369 issue = Issue.find(2) 434 issue = Issue.find(2)
370 assert issue.move_to_project(Project.find(2)) 435 assert issue.move_to_project(Project.find(2))
371 issue.reload 436 issue.reload
372 assert_equal 2, issue.project_id 437 assert_equal 2, issue.project_id
373 # Category cleared 438 # Category cleared
374 assert_nil issue.category_id 439 assert_nil issue.category_id
375 end 440 end
376 441
377 def test_move_to_another_project_should_clear_fixed_version_when_not_shared 442 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
378 issue = Issue.find(1) 443 issue = Issue.find(1)
379 issue.update_attribute(:fixed_version_id, 1) 444 issue.update_attribute(:fixed_version_id, 1)
380 assert issue.move_to_project(Project.find(2)) 445 assert issue.move_to_project(Project.find(2))
381 issue.reload 446 issue.reload
382 assert_equal 2, issue.project_id 447 assert_equal 2, issue.project_id
383 # Cleared fixed_version 448 # Cleared fixed_version
384 assert_equal nil, issue.fixed_version 449 assert_equal nil, issue.fixed_version
385 end 450 end
386 451
387 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project 452 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
388 issue = Issue.find(1) 453 issue = Issue.find(1)
389 issue.update_attribute(:fixed_version_id, 4) 454 issue.update_attribute(:fixed_version_id, 4)
390 assert issue.move_to_project(Project.find(5)) 455 assert issue.move_to_project(Project.find(5))
391 issue.reload 456 issue.reload
392 assert_equal 5, issue.project_id 457 assert_equal 5, issue.project_id
393 # Keep fixed_version 458 # Keep fixed_version
394 assert_equal 4, issue.fixed_version_id 459 assert_equal 4, issue.fixed_version_id
395 end 460 end
396 461
397 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project 462 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
398 issue = Issue.find(1) 463 issue = Issue.find(1)
399 issue.update_attribute(:fixed_version_id, 1) 464 issue.update_attribute(:fixed_version_id, 1)
400 assert issue.move_to_project(Project.find(5)) 465 assert issue.move_to_project(Project.find(5))
401 issue.reload 466 issue.reload
402 assert_equal 5, issue.project_id 467 assert_equal 5, issue.project_id
403 # Cleared fixed_version 468 # Cleared fixed_version
404 assert_equal nil, issue.fixed_version 469 assert_equal nil, issue.fixed_version
405 end 470 end
406 471
407 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide 472 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
408 issue = Issue.find(1) 473 issue = Issue.find(1)
409 issue.update_attribute(:fixed_version_id, 7) 474 issue.update_attribute(:fixed_version_id, 7)
410 assert issue.move_to_project(Project.find(2)) 475 assert issue.move_to_project(Project.find(2))
411 issue.reload 476 issue.reload
412 assert_equal 2, issue.project_id 477 assert_equal 2, issue.project_id
413 # Keep fixed_version 478 # Keep fixed_version
414 assert_equal 7, issue.fixed_version_id 479 assert_equal 7, issue.fixed_version_id
415 end 480 end
416 481
417 def test_move_to_another_project_with_disabled_tracker 482 def test_move_to_another_project_with_disabled_tracker
418 issue = Issue.find(1) 483 issue = Issue.find(1)
419 target = Project.find(2) 484 target = Project.find(2)
420 target.tracker_ids = [3] 485 target.tracker_ids = [3]
421 target.save 486 target.save
422 assert_equal false, issue.move_to_project(target) 487 assert_equal false, issue.move_to_project(target)
423 issue.reload 488 issue.reload
424 assert_equal 1, issue.project_id 489 assert_equal 1, issue.project_id
425 end 490 end
426 491
427 def test_copy_to_the_same_project 492 def test_copy_to_the_same_project
428 issue = Issue.find(1) 493 issue = Issue.find(1)
429 copy = nil 494 copy = nil
430 assert_difference 'Issue.count' do 495 assert_difference 'Issue.count' do
431 copy = issue.move_to_project(issue.project, nil, :copy => true) 496 copy = issue.move_to_project(issue.project, nil, :copy => true)
432 end 497 end
433 assert_kind_of Issue, copy 498 assert_kind_of Issue, copy
434 assert_equal issue.project, copy.project 499 assert_equal issue.project, copy.project
435 assert_equal "125", copy.custom_value_for(2).value 500 assert_equal "125", copy.custom_value_for(2).value
436 end 501 end
437 502
438 def test_copy_to_another_project_and_tracker 503 def test_copy_to_another_project_and_tracker
439 issue = Issue.find(1) 504 issue = Issue.find(1)
440 copy = nil 505 copy = nil
441 assert_difference 'Issue.count' do 506 assert_difference 'Issue.count' do
442 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true) 507 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
454 setup do 519 setup do
455 @issue = Issue.find(1) 520 @issue = Issue.find(1)
456 @copy = nil 521 @copy = nil
457 end 522 end
458 523
524 should "not create a journal" do
525 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
526 assert_equal 0, @copy.reload.journals.size
527 end
528
459 should "allow assigned_to changes" do 529 should "allow assigned_to changes" do
460 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}}) 530 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
461 assert_equal 3, @copy.assigned_to_id 531 assert_equal 3, @copy.assigned_to_id
462 end 532 end
463 533
476 date = Date.today 546 date = Date.today
477 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}}) 547 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
478 548
479 assert_equal date, @copy.due_date 549 assert_equal date, @copy.due_date
480 end 550 end
481 end 551
482 end 552 should "set current user as author" do
483 553 User.current = User.find(9)
554 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
555
556 assert_equal User.current, @copy.author
557 end
558
559 should "keep journal notes" do
560 date = Date.today
561 notes = "Notes added when copying"
562 User.current = User.find(9)
563 @issue.init_journal(User.current, notes)
564 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
565
566 assert_equal 1, @copy.journals.size
567 journal = @copy.journals.first
568 assert_equal 0, journal.details.size
569 assert_equal notes, journal.notes
570 end
571 end
572 end
573
484 def test_recipients_should_not_include_users_that_cannot_view_the_issue 574 def test_recipients_should_not_include_users_that_cannot_view_the_issue
485 issue = Issue.find(12) 575 issue = Issue.find(12)
486 assert issue.recipients.include?(issue.author.mail) 576 assert issue.recipients.include?(issue.author.mail)
487 # move the issue to a private project 577 # move the issue to a private project
488 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true) 578 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
495 issue = Issue.find(9) 585 issue = Issue.find(9)
496 Watcher.create!(:user => user, :watchable => issue) 586 Watcher.create!(:user => user, :watchable => issue)
497 assert issue.watched_by?(user) 587 assert issue.watched_by?(user)
498 assert !issue.watcher_recipients.include?(user.mail) 588 assert !issue.watcher_recipients.include?(user.mail)
499 end 589 end
500 590
501 def test_issue_destroy 591 def test_issue_destroy
502 Issue.find(1).destroy 592 Issue.find(1).destroy
503 assert_nil Issue.find_by_id(1) 593 assert_nil Issue.find_by_id(1)
504 assert_nil TimeEntry.find_by_issue_id(1) 594 assert_nil TimeEntry.find_by_issue_id(1)
505 end 595 end
506 596
507 def test_blocked 597 def test_blocked
508 blocked_issue = Issue.find(9) 598 blocked_issue = Issue.find(9)
509 blocking_issue = Issue.find(10) 599 blocking_issue = Issue.find(10)
510 600
511 assert blocked_issue.blocked? 601 assert blocked_issue.blocked?
512 assert !blocking_issue.blocked? 602 assert !blocking_issue.blocked?
513 end 603 end
514 604
515 def test_blocked_issues_dont_allow_closed_statuses 605 def test_blocked_issues_dont_allow_closed_statuses
516 blocked_issue = Issue.find(9) 606 blocked_issue = Issue.find(9)
517 607
518 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002)) 608 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
519 assert !allowed_statuses.empty? 609 assert !allowed_statuses.empty?
520 closed_statuses = allowed_statuses.select {|st| st.is_closed?} 610 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
521 assert closed_statuses.empty? 611 assert closed_statuses.empty?
522 end 612 end
523 613
524 def test_unblocked_issues_allow_closed_statuses 614 def test_unblocked_issues_allow_closed_statuses
525 blocking_issue = Issue.find(10) 615 blocking_issue = Issue.find(10)
526 616
527 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002)) 617 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
528 assert !allowed_statuses.empty? 618 assert !allowed_statuses.empty?
529 closed_statuses = allowed_statuses.select {|st| st.is_closed?} 619 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
530 assert !closed_statuses.empty? 620 assert !closed_statuses.empty?
531 end 621 end
532 622
533 def test_rescheduling_an_issue_should_reschedule_following_issue 623 def test_rescheduling_an_issue_should_reschedule_following_issue
534 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2) 624 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
535 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2) 625 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
536 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES) 626 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
537 assert_equal issue1.due_date + 1, issue2.reload.start_date 627 assert_equal issue1.due_date + 1, issue2.reload.start_date
538 628
539 issue1.due_date = Date.today + 5 629 issue1.due_date = Date.today + 5
540 issue1.save! 630 issue1.save!
541 assert_equal issue1.due_date + 1, issue2.reload.start_date 631 assert_equal issue1.due_date + 1, issue2.reload.start_date
542 end 632 end
543 633
544 def test_overdue 634 def test_overdue
545 assert Issue.new(:due_date => 1.day.ago.to_date).overdue? 635 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
546 assert !Issue.new(:due_date => Date.today).overdue? 636 assert !Issue.new(:due_date => Date.today).overdue?
547 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue? 637 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
548 assert !Issue.new(:due_date => nil).overdue? 638 assert !Issue.new(:due_date => nil).overdue?
585 end 675 end
586 676
587 should "not show the issue author twice" do 677 should "not show the issue author twice" do
588 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id) 678 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
589 assert_equal 2, assignable_user_ids.length 679 assert_equal 2, assignable_user_ids.length
590 680
591 assignable_user_ids.each do |user_id| 681 assignable_user_ids.each do |user_id|
592 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once" 682 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
593 end 683 end
594 end 684 end
595 end 685 end
596 686
597 def test_create_should_send_email_notification 687 def test_create_should_send_email_notification
598 ActionMailer::Base.deliveries.clear 688 ActionMailer::Base.deliveries.clear
599 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :estimated_hours => '1:30') 689 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :estimated_hours => '1:30')
600 690
601 assert issue.save 691 assert issue.save
604 694
605 def test_stale_issue_should_not_send_email_notification 695 def test_stale_issue_should_not_send_email_notification
606 ActionMailer::Base.deliveries.clear 696 ActionMailer::Base.deliveries.clear
607 issue = Issue.find(1) 697 issue = Issue.find(1)
608 stale = Issue.find(1) 698 stale = Issue.find(1)
609 699
610 issue.init_journal(User.find(1)) 700 issue.init_journal(User.find(1))
611 issue.subject = 'Subjet update' 701 issue.subject = 'Subjet update'
612 assert issue.save 702 assert issue.save
613 assert_equal 1, ActionMailer::Base.deliveries.size 703 assert_equal 1, ActionMailer::Base.deliveries.size
614 ActionMailer::Base.deliveries.clear 704 ActionMailer::Base.deliveries.clear
615 705
616 stale.init_journal(User.find(1)) 706 stale.init_journal(User.find(1))
617 stale.subject = 'Another subjet update' 707 stale.subject = 'Another subjet update'
618 assert_raise ActiveRecord::StaleObjectError do 708 assert_raise ActiveRecord::StaleObjectError do
619 stale.save 709 stale.save
620 end 710 end
621 assert ActionMailer::Base.deliveries.empty? 711 assert ActionMailer::Base.deliveries.empty?
622 end 712 end
623 713
624 def test_journalized_description 714 def test_journalized_description
625 IssueCustomField.delete_all 715 IssueCustomField.delete_all
626 716
627 i = Issue.first 717 i = Issue.first
628 old_description = i.description 718 old_description = i.description
629 new_description = "This is the new description" 719 new_description = "This is the new description"
630 720
631 i.init_journal(User.find(2)) 721 i.init_journal(User.find(2))
632 i.description = new_description 722 i.description = new_description
633 assert_difference 'Journal.count', 1 do 723 assert_difference 'Journal.count', 1 do
634 assert_difference 'JournalDetail.count', 1 do 724 assert_difference 'JournalDetail.count', 1 do
635 i.save! 725 i.save!
636 end 726 end
637 end 727 end
638 728
639 detail = JournalDetail.first(:order => 'id DESC') 729 detail = JournalDetail.first(:order => 'id DESC')
640 assert_equal i, detail.journal.journalized 730 assert_equal i, detail.journal.journalized
641 assert_equal 'attr', detail.property 731 assert_equal 'attr', detail.property
642 assert_equal 'description', detail.prop_key 732 assert_equal 'description', detail.prop_key
643 assert_equal old_description, detail.old_value 733 assert_equal old_description, detail.old_value
644 assert_equal new_description, detail.value 734 assert_equal new_description, detail.value
645 end 735 end
646 736
647 def test_saving_twice_should_not_duplicate_journal_details 737 def test_saving_twice_should_not_duplicate_journal_details
648 i = Issue.find(:first) 738 i = Issue.find(:first)
649 i.init_journal(User.find(2), 'Some notes') 739 i.init_journal(User.find(2), 'Some notes')
650 # initial changes 740 # initial changes
651 i.subject = 'New subject' 741 i.subject = 'New subject'
671 def test_all_dependent_issues 761 def test_all_dependent_issues
672 IssueRelation.delete_all 762 IssueRelation.delete_all
673 assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_PRECEDES) 763 assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_PRECEDES)
674 assert IssueRelation.create!(:issue_from => Issue.find(2), :issue_to => Issue.find(3), :relation_type => IssueRelation::TYPE_PRECEDES) 764 assert IssueRelation.create!(:issue_from => Issue.find(2), :issue_to => Issue.find(3), :relation_type => IssueRelation::TYPE_PRECEDES)
675 assert IssueRelation.create!(:issue_from => Issue.find(3), :issue_to => Issue.find(8), :relation_type => IssueRelation::TYPE_PRECEDES) 765 assert IssueRelation.create!(:issue_from => Issue.find(3), :issue_to => Issue.find(8), :relation_type => IssueRelation::TYPE_PRECEDES)
676 766
677 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort 767 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
678 end 768 end
679 769
680 def test_all_dependent_issues_with_persistent_circular_dependency 770 def test_all_dependent_issues_with_persistent_circular_dependency
681 IssueRelation.delete_all 771 IssueRelation.delete_all
682 assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_PRECEDES) 772 assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_PRECEDES)
683 assert IssueRelation.create!(:issue_from => Issue.find(2), :issue_to => Issue.find(3), :relation_type => IssueRelation::TYPE_PRECEDES) 773 assert IssueRelation.create!(:issue_from => Issue.find(2), :issue_to => Issue.find(3), :relation_type => IssueRelation::TYPE_PRECEDES)
684 # Validation skipping 774 # Validation skipping
685 assert IssueRelation.new(:issue_from => Issue.find(3), :issue_to => Issue.find(1), :relation_type => IssueRelation::TYPE_PRECEDES).save(false) 775 assert IssueRelation.new(:issue_from => Issue.find(3), :issue_to => Issue.find(1), :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
686 776
687 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort 777 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
688 end 778 end
689 779
780 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
781 IssueRelation.delete_all
782 assert IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_RELATES)
783 assert IssueRelation.create!(:issue_from => Issue.find(2), :issue_to => Issue.find(3), :relation_type => IssueRelation::TYPE_RELATES)
784 assert IssueRelation.create!(:issue_from => Issue.find(3), :issue_to => Issue.find(8), :relation_type => IssueRelation::TYPE_RELATES)
785 # Validation skipping
786 assert IssueRelation.new(:issue_from => Issue.find(8), :issue_to => Issue.find(2), :relation_type => IssueRelation::TYPE_RELATES).save(false)
787 assert IssueRelation.new(:issue_from => Issue.find(3), :issue_to => Issue.find(1), :relation_type => IssueRelation::TYPE_RELATES).save(false)
788
789 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
790 end
791
690 context "#done_ratio" do 792 context "#done_ratio" do
691 setup do 793 setup do
692 @issue = Issue.find(1) 794 @issue = Issue.find(1)
693 @issue_status = IssueStatus.find(1) 795 @issue_status = IssueStatus.find(1)
694 @issue_status.update_attribute(:default_done_ratio, 50) 796 @issue_status.update_attribute(:default_done_ratio, 50)
695 @issue2 = Issue.find(2) 797 @issue2 = Issue.find(2)
696 @issue_status2 = IssueStatus.find(2) 798 @issue_status2 = IssueStatus.find(2)
697 @issue_status2.update_attribute(:default_done_ratio, 0) 799 @issue_status2.update_attribute(:default_done_ratio, 0)
698 end 800 end
699 801
700 context "with Setting.issue_done_ratio using the issue_field" do 802 context "with Setting.issue_done_ratio using the issue_field" do
701 setup do 803 setup do
702 Setting.issue_done_ratio = 'issue_field' 804 Setting.issue_done_ratio = 'issue_field'
703 end 805 end
704 806
705 should "read the issue's field" do 807 should "read the issue's field" do
706 assert_equal 0, @issue.done_ratio 808 assert_equal 0, @issue.done_ratio
707 assert_equal 30, @issue2.done_ratio 809 assert_equal 30, @issue2.done_ratio
708 end 810 end
709 end 811 end
710 812
711 context "with Setting.issue_done_ratio using the issue_status" do 813 context "with Setting.issue_done_ratio using the issue_status" do
712 setup do 814 setup do
713 Setting.issue_done_ratio = 'issue_status' 815 Setting.issue_done_ratio = 'issue_status'
714 end 816 end
715 817
716 should "read the Issue Status's default done ratio" do 818 should "read the Issue Status's default done ratio" do
717 assert_equal 50, @issue.done_ratio 819 assert_equal 50, @issue.done_ratio
718 assert_equal 0, @issue2.done_ratio 820 assert_equal 0, @issue2.done_ratio
719 end 821 end
720 end 822 end
727 @issue_status.update_attribute(:default_done_ratio, 50) 829 @issue_status.update_attribute(:default_done_ratio, 50)
728 @issue2 = Issue.find(2) 830 @issue2 = Issue.find(2)
729 @issue_status2 = IssueStatus.find(2) 831 @issue_status2 = IssueStatus.find(2)
730 @issue_status2.update_attribute(:default_done_ratio, 0) 832 @issue_status2.update_attribute(:default_done_ratio, 0)
731 end 833 end
732 834
733 context "with Setting.issue_done_ratio using the issue_field" do 835 context "with Setting.issue_done_ratio using the issue_field" do
734 setup do 836 setup do
735 Setting.issue_done_ratio = 'issue_field' 837 Setting.issue_done_ratio = 'issue_field'
736 end 838 end
737 839
738 should "not change the issue" do 840 should "not change the issue" do
739 @issue.update_done_ratio_from_issue_status 841 @issue.update_done_ratio_from_issue_status
740 @issue2.update_done_ratio_from_issue_status 842 @issue2.update_done_ratio_from_issue_status
741 843
742 assert_equal 0, @issue.read_attribute(:done_ratio) 844 assert_equal 0, @issue.read_attribute(:done_ratio)
746 848
747 context "with Setting.issue_done_ratio using the issue_status" do 849 context "with Setting.issue_done_ratio using the issue_status" do
748 setup do 850 setup do
749 Setting.issue_done_ratio = 'issue_status' 851 Setting.issue_done_ratio = 'issue_status'
750 end 852 end
751 853
752 should "change the issue's done ratio" do 854 should "change the issue's done ratio" do
753 @issue.update_done_ratio_from_issue_status 855 @issue.update_done_ratio_from_issue_status
754 @issue2.update_done_ratio_from_issue_status 856 @issue2.update_done_ratio_from_issue_status
755 857
756 assert_equal 50, @issue.read_attribute(:done_ratio) 858 assert_equal 50, @issue.read_attribute(:done_ratio)
758 end 860 end
759 end 861 end
760 end 862 end
761 863
762 test "#by_tracker" do 864 test "#by_tracker" do
865 User.current = User.anonymous
763 groups = Issue.by_tracker(Project.find(1)) 866 groups = Issue.by_tracker(Project.find(1))
764 assert_equal 3, groups.size 867 assert_equal 3, groups.size
765 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} 868 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
766 end 869 end
767 870
768 test "#by_version" do 871 test "#by_version" do
872 User.current = User.anonymous
769 groups = Issue.by_version(Project.find(1)) 873 groups = Issue.by_version(Project.find(1))
770 assert_equal 3, groups.size 874 assert_equal 3, groups.size
771 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} 875 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
772 end 876 end
773 877
774 test "#by_priority" do 878 test "#by_priority" do
879 User.current = User.anonymous
775 groups = Issue.by_priority(Project.find(1)) 880 groups = Issue.by_priority(Project.find(1))
776 assert_equal 4, groups.size 881 assert_equal 4, groups.size
777 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} 882 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
778 end 883 end
779 884
780 test "#by_category" do 885 test "#by_category" do
886 User.current = User.anonymous
781 groups = Issue.by_category(Project.find(1)) 887 groups = Issue.by_category(Project.find(1))
782 assert_equal 2, groups.size 888 assert_equal 2, groups.size
783 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} 889 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
784 end 890 end
785 891
786 test "#by_assigned_to" do 892 test "#by_assigned_to" do
893 User.current = User.anonymous
787 groups = Issue.by_assigned_to(Project.find(1)) 894 groups = Issue.by_assigned_to(Project.find(1))
788 assert_equal 2, groups.size 895 assert_equal 2, groups.size
789 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} 896 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
790 end 897 end
791 898
792 test "#by_author" do 899 test "#by_author" do
900 User.current = User.anonymous
793 groups = Issue.by_author(Project.find(1)) 901 groups = Issue.by_author(Project.find(1))
794 assert_equal 4, groups.size 902 assert_equal 4, groups.size
795 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} 903 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
796 end 904 end
797 905
798 test "#by_subproject" do 906 test "#by_subproject" do
907 User.current = User.anonymous
799 groups = Issue.by_subproject(Project.find(1)) 908 groups = Issue.by_subproject(Project.find(1))
800 assert_equal 2, groups.size 909 # Private descendant not visible
801 assert_equal 5, groups.inject(0) {|sum, group| sum + group['total'].to_i} 910 assert_equal 1, groups.size
802 end 911 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
803 912 end
804 913
805 context ".allowed_target_projects_on_move" do 914 context ".allowed_target_projects_on_move" do
806 should "return all active projects for admin users" do 915 should "return all active projects for admin users" do
807 User.current = User.find(1) 916 User.current = User.find(1)
808 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size 917 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
809 end 918 end
810 919
811 should "return allowed projects for non admin users" do 920 should "return allowed projects for non admin users" do
812 User.current = User.find(2) 921 User.current = User.find(2)
813 Role.non_member.remove_permission! :move_issues 922 Role.non_member.remove_permission! :move_issues
814 assert_equal 3, Issue.allowed_target_projects_on_move.size 923 assert_equal 3, Issue.allowed_target_projects_on_move.size
815 924
816 Role.non_member.add_permission! :move_issues 925 Role.non_member.add_permission! :move_issues
817 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size 926 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
818 end 927 end
819 end 928 end
820 929
824 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first 933 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
825 end 934 end
826 935
827 def test_on_active_projects_scope 936 def test_on_active_projects_scope
828 assert Project.find(2).archive 937 assert Project.find(2).archive
829 938
830 before = Issue.on_active_project.length 939 before = Issue.on_active_project.length
831 # test inclusion to results 940 # test inclusion to results
832 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first) 941 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
833 assert_equal before + 1, Issue.on_active_project.length 942 assert_equal before + 1, Issue.on_active_project.length
834 943
843 @project = Project.find(1) 952 @project = Project.find(1)
844 @author = User.generate_with_protected! 953 @author = User.generate_with_protected!
845 @assignee = User.generate_with_protected! 954 @assignee = User.generate_with_protected!
846 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author) 955 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
847 end 956 end
848 957
849 should "include project recipients" do 958 should "include project recipients" do
850 assert @project.recipients.present? 959 assert @project.recipients.present?
851 @project.recipients.each do |project_recipient| 960 @project.recipients.each do |project_recipient|
852 assert @issue.recipients.include?(project_recipient) 961 assert @issue.recipients.include?(project_recipient)
853 end 962 end
855 964
856 should "include the author if the author is active" do 965 should "include the author if the author is active" do
857 assert @issue.author, "No author set for Issue" 966 assert @issue.author, "No author set for Issue"
858 assert @issue.recipients.include?(@issue.author.mail) 967 assert @issue.recipients.include?(@issue.author.mail)
859 end 968 end
860 969
861 should "include the assigned to user if the assigned to user is active" do 970 should "include the assigned to user if the assigned to user is active" do
862 assert @issue.assigned_to, "No assigned_to set for Issue" 971 assert @issue.assigned_to, "No assigned_to set for Issue"
863 assert @issue.recipients.include?(@issue.assigned_to.mail) 972 assert @issue.recipients.include?(@issue.assigned_to.mail)
864 end 973 end
865 974