##// END OF EJS Templates
code layout clean up of test_visible_scope_for_anonymous_with_own_issues_visibility at test/unit/issue_test.rb...
Toshi MARUYAMA -
r7486:9f7690873a9e
parent child
Show More
@@ -1,1109 +1,1111
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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, :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
31 def test_create
31 def test_create
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
33 :status_id => 1, :priority => IssuePriority.all.first,
33 :status_id => 1, :priority => IssuePriority.all.first,
34 :subject => 'test_create',
34 :subject => 'test_create',
35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
36 assert issue.save
36 assert issue.save
37 issue.reload
37 issue.reload
38 assert_equal 1.5, issue.estimated_hours
38 assert_equal 1.5, issue.estimated_hours
39 end
39 end
40
40
41 def test_create_minimal
41 def test_create_minimal
42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
43 :status_id => 1, :priority => IssuePriority.all.first,
43 :status_id => 1, :priority => IssuePriority.all.first,
44 :subject => 'test_create')
44 :subject => 'test_create')
45 assert issue.save
45 assert issue.save
46 assert issue.description.nil?
46 assert issue.description.nil?
47 end
47 end
48
48
49 def test_create_with_required_custom_field
49 def test_create_with_required_custom_field
50 field = IssueCustomField.find_by_name('Database')
50 field = IssueCustomField.find_by_name('Database')
51 field.update_attribute(:is_required, true)
51 field.update_attribute(:is_required, true)
52
52
53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
54 :status_id => 1, :subject => 'test_create',
54 :status_id => 1, :subject => 'test_create',
55 :description => 'IssueTest#test_create_with_required_custom_field')
55 :description => 'IssueTest#test_create_with_required_custom_field')
56 assert issue.available_custom_fields.include?(field)
56 assert issue.available_custom_fields.include?(field)
57 # No value for the custom field
57 # No value for the custom field
58 assert !issue.save
58 assert !issue.save
59 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
59 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
60 # Blank value
60 # Blank value
61 issue.custom_field_values = { field.id => '' }
61 issue.custom_field_values = { field.id => '' }
62 assert !issue.save
62 assert !issue.save
63 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
63 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
64 # Invalid value
64 # Invalid value
65 issue.custom_field_values = { field.id => 'SQLServer' }
65 issue.custom_field_values = { field.id => 'SQLServer' }
66 assert !issue.save
66 assert !issue.save
67 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
67 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
68 # Valid value
68 # Valid value
69 issue.custom_field_values = { field.id => 'PostgreSQL' }
69 issue.custom_field_values = { field.id => 'PostgreSQL' }
70 assert issue.save
70 assert issue.save
71 issue.reload
71 issue.reload
72 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
72 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
73 end
73 end
74
74
75 def test_create_with_group_assignment
75 def test_create_with_group_assignment
76 with_settings :issue_group_assignment => '1' do
76 with_settings :issue_group_assignment => '1' do
77 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
77 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
78 :subject => 'Group assignment',
78 :subject => 'Group assignment',
79 :assigned_to_id => 11).save
79 :assigned_to_id => 11).save
80 issue = Issue.first(:order => 'id DESC')
80 issue = Issue.first(:order => 'id DESC')
81 assert_kind_of Group, issue.assigned_to
81 assert_kind_of Group, issue.assigned_to
82 assert_equal Group.find(11), issue.assigned_to
82 assert_equal Group.find(11), issue.assigned_to
83 end
83 end
84 end
84 end
85
85
86 def assert_visibility_match(user, issues)
86 def assert_visibility_match(user, issues)
87 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
87 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
88 end
88 end
89
89
90 def test_visible_scope_for_anonymous
90 def test_visible_scope_for_anonymous
91 # Anonymous user should see issues of public projects only
91 # Anonymous user should see issues of public projects only
92 issues = Issue.visible(User.anonymous).all
92 issues = Issue.visible(User.anonymous).all
93 assert issues.any?
93 assert issues.any?
94 assert_nil issues.detect {|issue| !issue.project.is_public?}
94 assert_nil issues.detect {|issue| !issue.project.is_public?}
95 assert_nil issues.detect {|issue| issue.is_private?}
95 assert_nil issues.detect {|issue| issue.is_private?}
96 assert_visibility_match User.anonymous, issues
96 assert_visibility_match User.anonymous, issues
97 end
97 end
98
98
99 def test_visible_scope_for_anonymous_with_own_issues_visibility
99 def test_visible_scope_for_anonymous_with_own_issues_visibility
100 Role.anonymous.update_attribute :issues_visibility, 'own'
100 Role.anonymous.update_attribute :issues_visibility, 'own'
101 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => User.anonymous.id, :subject => 'Issue by anonymous')
101 Issue.create!(:project_id => 1, :tracker_id => 1,
102 :author_id => User.anonymous.id,
103 :subject => 'Issue by anonymous')
102
104
103 issues = Issue.visible(User.anonymous).all
105 issues = Issue.visible(User.anonymous).all
104 assert issues.any?
106 assert issues.any?
105 assert_nil issues.detect {|issue| issue.author != User.anonymous}
107 assert_nil issues.detect {|issue| issue.author != User.anonymous}
106 assert_visibility_match User.anonymous, issues
108 assert_visibility_match User.anonymous, issues
107 end
109 end
108
110
109 def test_visible_scope_for_anonymous_without_view_issues_permissions
111 def test_visible_scope_for_anonymous_without_view_issues_permissions
110 # Anonymous user should not see issues without permission
112 # Anonymous user should not see issues without permission
111 Role.anonymous.remove_permission!(:view_issues)
113 Role.anonymous.remove_permission!(:view_issues)
112 issues = Issue.visible(User.anonymous).all
114 issues = Issue.visible(User.anonymous).all
113 assert issues.empty?
115 assert issues.empty?
114 assert_visibility_match User.anonymous, issues
116 assert_visibility_match User.anonymous, issues
115 end
117 end
116
118
117 def test_visible_scope_for_non_member
119 def test_visible_scope_for_non_member
118 user = User.find(9)
120 user = User.find(9)
119 assert user.projects.empty?
121 assert user.projects.empty?
120 # Non member user should see issues of public projects only
122 # Non member user should see issues of public projects only
121 issues = Issue.visible(user).all
123 issues = Issue.visible(user).all
122 assert issues.any?
124 assert issues.any?
123 assert_nil issues.detect {|issue| !issue.project.is_public?}
125 assert_nil issues.detect {|issue| !issue.project.is_public?}
124 assert_nil issues.detect {|issue| issue.is_private?}
126 assert_nil issues.detect {|issue| issue.is_private?}
125 assert_visibility_match user, issues
127 assert_visibility_match user, issues
126 end
128 end
127
129
128 def test_visible_scope_for_non_member_with_own_issues_visibility
130 def test_visible_scope_for_non_member_with_own_issues_visibility
129 Role.non_member.update_attribute :issues_visibility, 'own'
131 Role.non_member.update_attribute :issues_visibility, 'own'
130 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
132 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
131 user = User.find(9)
133 user = User.find(9)
132
134
133 issues = Issue.visible(user).all
135 issues = Issue.visible(user).all
134 assert issues.any?
136 assert issues.any?
135 assert_nil issues.detect {|issue| issue.author != user}
137 assert_nil issues.detect {|issue| issue.author != user}
136 assert_visibility_match user, issues
138 assert_visibility_match user, issues
137 end
139 end
138
140
139 def test_visible_scope_for_non_member_without_view_issues_permissions
141 def test_visible_scope_for_non_member_without_view_issues_permissions
140 # Non member user should not see issues without permission
142 # Non member user should not see issues without permission
141 Role.non_member.remove_permission!(:view_issues)
143 Role.non_member.remove_permission!(:view_issues)
142 user = User.find(9)
144 user = User.find(9)
143 assert user.projects.empty?
145 assert user.projects.empty?
144 issues = Issue.visible(user).all
146 issues = Issue.visible(user).all
145 assert issues.empty?
147 assert issues.empty?
146 assert_visibility_match user, issues
148 assert_visibility_match user, issues
147 end
149 end
148
150
149 def test_visible_scope_for_member
151 def test_visible_scope_for_member
150 user = User.find(9)
152 user = User.find(9)
151 # User should see issues of projects for which he has view_issues permissions only
153 # User should see issues of projects for which he has view_issues permissions only
152 Role.non_member.remove_permission!(:view_issues)
154 Role.non_member.remove_permission!(:view_issues)
153 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
155 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
154 issues = Issue.visible(user).all
156 issues = Issue.visible(user).all
155 assert issues.any?
157 assert issues.any?
156 assert_nil issues.detect {|issue| issue.project_id != 3}
158 assert_nil issues.detect {|issue| issue.project_id != 3}
157 assert_nil issues.detect {|issue| issue.is_private?}
159 assert_nil issues.detect {|issue| issue.is_private?}
158 assert_visibility_match user, issues
160 assert_visibility_match user, issues
159 end
161 end
160
162
161 def test_visible_scope_for_admin
163 def test_visible_scope_for_admin
162 user = User.find(1)
164 user = User.find(1)
163 user.members.each(&:destroy)
165 user.members.each(&:destroy)
164 assert user.projects.empty?
166 assert user.projects.empty?
165 issues = Issue.visible(user).all
167 issues = Issue.visible(user).all
166 assert issues.any?
168 assert issues.any?
167 # Admin should see issues on private projects that he does not belong to
169 # Admin should see issues on private projects that he does not belong to
168 assert issues.detect {|issue| !issue.project.is_public?}
170 assert issues.detect {|issue| !issue.project.is_public?}
169 # Admin should see private issues of other users
171 # Admin should see private issues of other users
170 assert issues.detect {|issue| issue.is_private? && issue.author != user}
172 assert issues.detect {|issue| issue.is_private? && issue.author != user}
171 assert_visibility_match user, issues
173 assert_visibility_match user, issues
172 end
174 end
173
175
174 def test_visible_scope_with_project
176 def test_visible_scope_with_project
175 project = Project.find(1)
177 project = Project.find(1)
176 issues = Issue.visible(User.find(2), :project => project).all
178 issues = Issue.visible(User.find(2), :project => project).all
177 projects = issues.collect(&:project).uniq
179 projects = issues.collect(&:project).uniq
178 assert_equal 1, projects.size
180 assert_equal 1, projects.size
179 assert_equal project, projects.first
181 assert_equal project, projects.first
180 end
182 end
181
183
182 def test_visible_scope_with_project_and_subprojects
184 def test_visible_scope_with_project_and_subprojects
183 project = Project.find(1)
185 project = Project.find(1)
184 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
186 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
185 projects = issues.collect(&:project).uniq
187 projects = issues.collect(&:project).uniq
186 assert projects.size > 1
188 assert projects.size > 1
187 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
189 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
188 end
190 end
189
191
190 def test_visible_and_nested_set_scopes
192 def test_visible_and_nested_set_scopes
191 assert_equal 0, Issue.find(1).descendants.visible.all.size
193 assert_equal 0, Issue.find(1).descendants.visible.all.size
192 end
194 end
193
195
194 def test_errors_full_messages_should_include_custom_fields_errors
196 def test_errors_full_messages_should_include_custom_fields_errors
195 field = IssueCustomField.find_by_name('Database')
197 field = IssueCustomField.find_by_name('Database')
196
198
197 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
199 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
198 :status_id => 1, :subject => 'test_create',
200 :status_id => 1, :subject => 'test_create',
199 :description => 'IssueTest#test_create_with_required_custom_field')
201 :description => 'IssueTest#test_create_with_required_custom_field')
200 assert issue.available_custom_fields.include?(field)
202 assert issue.available_custom_fields.include?(field)
201 # Invalid value
203 # Invalid value
202 issue.custom_field_values = { field.id => 'SQLServer' }
204 issue.custom_field_values = { field.id => 'SQLServer' }
203
205
204 assert !issue.valid?
206 assert !issue.valid?
205 assert_equal 1, issue.errors.full_messages.size
207 assert_equal 1, issue.errors.full_messages.size
206 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
208 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
207 issue.errors.full_messages.first
209 issue.errors.full_messages.first
208 end
210 end
209
211
210 def test_update_issue_with_required_custom_field
212 def test_update_issue_with_required_custom_field
211 field = IssueCustomField.find_by_name('Database')
213 field = IssueCustomField.find_by_name('Database')
212 field.update_attribute(:is_required, true)
214 field.update_attribute(:is_required, true)
213
215
214 issue = Issue.find(1)
216 issue = Issue.find(1)
215 assert_nil issue.custom_value_for(field)
217 assert_nil issue.custom_value_for(field)
216 assert issue.available_custom_fields.include?(field)
218 assert issue.available_custom_fields.include?(field)
217 # No change to custom values, issue can be saved
219 # No change to custom values, issue can be saved
218 assert issue.save
220 assert issue.save
219 # Blank value
221 # Blank value
220 issue.custom_field_values = { field.id => '' }
222 issue.custom_field_values = { field.id => '' }
221 assert !issue.save
223 assert !issue.save
222 # Valid value
224 # Valid value
223 issue.custom_field_values = { field.id => 'PostgreSQL' }
225 issue.custom_field_values = { field.id => 'PostgreSQL' }
224 assert issue.save
226 assert issue.save
225 issue.reload
227 issue.reload
226 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
228 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
227 end
229 end
228
230
229 def test_should_not_update_attributes_if_custom_fields_validation_fails
231 def test_should_not_update_attributes_if_custom_fields_validation_fails
230 issue = Issue.find(1)
232 issue = Issue.find(1)
231 field = IssueCustomField.find_by_name('Database')
233 field = IssueCustomField.find_by_name('Database')
232 assert issue.available_custom_fields.include?(field)
234 assert issue.available_custom_fields.include?(field)
233
235
234 issue.custom_field_values = { field.id => 'Invalid' }
236 issue.custom_field_values = { field.id => 'Invalid' }
235 issue.subject = 'Should be not be saved'
237 issue.subject = 'Should be not be saved'
236 assert !issue.save
238 assert !issue.save
237
239
238 issue.reload
240 issue.reload
239 assert_equal "Can't print recipes", issue.subject
241 assert_equal "Can't print recipes", issue.subject
240 end
242 end
241
243
242 def test_should_not_recreate_custom_values_objects_on_update
244 def test_should_not_recreate_custom_values_objects_on_update
243 field = IssueCustomField.find_by_name('Database')
245 field = IssueCustomField.find_by_name('Database')
244
246
245 issue = Issue.find(1)
247 issue = Issue.find(1)
246 issue.custom_field_values = { field.id => 'PostgreSQL' }
248 issue.custom_field_values = { field.id => 'PostgreSQL' }
247 assert issue.save
249 assert issue.save
248 custom_value = issue.custom_value_for(field)
250 custom_value = issue.custom_value_for(field)
249 issue.reload
251 issue.reload
250 issue.custom_field_values = { field.id => 'MySQL' }
252 issue.custom_field_values = { field.id => 'MySQL' }
251 assert issue.save
253 assert issue.save
252 issue.reload
254 issue.reload
253 assert_equal custom_value.id, issue.custom_value_for(field).id
255 assert_equal custom_value.id, issue.custom_value_for(field).id
254 end
256 end
255
257
256 def test_assigning_tracker_id_should_reload_custom_fields_values
258 def test_assigning_tracker_id_should_reload_custom_fields_values
257 issue = Issue.new(:project => Project.find(1))
259 issue = Issue.new(:project => Project.find(1))
258 assert issue.custom_field_values.empty?
260 assert issue.custom_field_values.empty?
259 issue.tracker_id = 1
261 issue.tracker_id = 1
260 assert issue.custom_field_values.any?
262 assert issue.custom_field_values.any?
261 end
263 end
262
264
263 def test_assigning_attributes_should_assign_tracker_id_first
265 def test_assigning_attributes_should_assign_tracker_id_first
264 attributes = ActiveSupport::OrderedHash.new
266 attributes = ActiveSupport::OrderedHash.new
265 attributes['custom_field_values'] = { '1' => 'MySQL' }
267 attributes['custom_field_values'] = { '1' => 'MySQL' }
266 attributes['tracker_id'] = '1'
268 attributes['tracker_id'] = '1'
267 issue = Issue.new(:project => Project.find(1))
269 issue = Issue.new(:project => Project.find(1))
268 issue.attributes = attributes
270 issue.attributes = attributes
269 assert_not_nil issue.custom_value_for(1)
271 assert_not_nil issue.custom_value_for(1)
270 assert_equal 'MySQL', issue.custom_value_for(1).value
272 assert_equal 'MySQL', issue.custom_value_for(1).value
271 end
273 end
272
274
273 def test_should_update_issue_with_disabled_tracker
275 def test_should_update_issue_with_disabled_tracker
274 p = Project.find(1)
276 p = Project.find(1)
275 issue = Issue.find(1)
277 issue = Issue.find(1)
276
278
277 p.trackers.delete(issue.tracker)
279 p.trackers.delete(issue.tracker)
278 assert !p.trackers.include?(issue.tracker)
280 assert !p.trackers.include?(issue.tracker)
279
281
280 issue.reload
282 issue.reload
281 issue.subject = 'New subject'
283 issue.subject = 'New subject'
282 assert issue.save
284 assert issue.save
283 end
285 end
284
286
285 def test_should_not_set_a_disabled_tracker
287 def test_should_not_set_a_disabled_tracker
286 p = Project.find(1)
288 p = Project.find(1)
287 p.trackers.delete(Tracker.find(2))
289 p.trackers.delete(Tracker.find(2))
288
290
289 issue = Issue.find(1)
291 issue = Issue.find(1)
290 issue.tracker_id = 2
292 issue.tracker_id = 2
291 issue.subject = 'New subject'
293 issue.subject = 'New subject'
292 assert !issue.save
294 assert !issue.save
293 assert_not_nil issue.errors[:tracker_id]
295 assert_not_nil issue.errors[:tracker_id]
294 end
296 end
295
297
296 def test_category_based_assignment
298 def test_category_based_assignment
297 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
299 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
298 :status_id => 1, :priority => IssuePriority.all.first,
300 :status_id => 1, :priority => IssuePriority.all.first,
299 :subject => 'Assignment test',
301 :subject => 'Assignment test',
300 :description => 'Assignment test', :category_id => 1)
302 :description => 'Assignment test', :category_id => 1)
301 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
303 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
302 end
304 end
303
305
304 def test_new_statuses_allowed_to
306 def test_new_statuses_allowed_to
305 Workflow.delete_all
307 Workflow.delete_all
306
308
307 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
309 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
308 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
310 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
309 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
311 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
310 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
312 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
311 status = IssueStatus.find(1)
313 status = IssueStatus.find(1)
312 role = Role.find(1)
314 role = Role.find(1)
313 tracker = Tracker.find(1)
315 tracker = Tracker.find(1)
314 user = User.find(2)
316 user = User.find(2)
315
317
316 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
318 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
317 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
319 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
318
320
319 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
321 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
320 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
322 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
321
323
322 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
324 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
323 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
325 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
324
326
325 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
327 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
326 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
328 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
327 end
329 end
328
330
329 def test_copy
331 def test_copy
330 issue = Issue.new.copy_from(1)
332 issue = Issue.new.copy_from(1)
331 assert issue.save
333 assert issue.save
332 issue.reload
334 issue.reload
333 orig = Issue.find(1)
335 orig = Issue.find(1)
334 assert_equal orig.subject, issue.subject
336 assert_equal orig.subject, issue.subject
335 assert_equal orig.tracker, issue.tracker
337 assert_equal orig.tracker, issue.tracker
336 assert_equal "125", issue.custom_value_for(2).value
338 assert_equal "125", issue.custom_value_for(2).value
337 end
339 end
338
340
339 def test_copy_should_copy_status
341 def test_copy_should_copy_status
340 orig = Issue.find(8)
342 orig = Issue.find(8)
341 assert orig.status != IssueStatus.default
343 assert orig.status != IssueStatus.default
342
344
343 issue = Issue.new.copy_from(orig)
345 issue = Issue.new.copy_from(orig)
344 assert issue.save
346 assert issue.save
345 issue.reload
347 issue.reload
346 assert_equal orig.status, issue.status
348 assert_equal orig.status, issue.status
347 end
349 end
348
350
349 def test_should_close_duplicates
351 def test_should_close_duplicates
350 # Create 3 issues
352 # Create 3 issues
351 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
353 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
352 :status_id => 1, :priority => IssuePriority.all.first,
354 :status_id => 1, :priority => IssuePriority.all.first,
353 :subject => 'Duplicates test', :description => 'Duplicates test')
355 :subject => 'Duplicates test', :description => 'Duplicates test')
354 assert issue1.save
356 assert issue1.save
355 issue2 = issue1.clone
357 issue2 = issue1.clone
356 assert issue2.save
358 assert issue2.save
357 issue3 = issue1.clone
359 issue3 = issue1.clone
358 assert issue3.save
360 assert issue3.save
359
361
360 # 2 is a dupe of 1
362 # 2 is a dupe of 1
361 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
363 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
362 # And 3 is a dupe of 2
364 # And 3 is a dupe of 2
363 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
365 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
364 # And 3 is a dupe of 1 (circular duplicates)
366 # And 3 is a dupe of 1 (circular duplicates)
365 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
367 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
366
368
367 assert issue1.reload.duplicates.include?(issue2)
369 assert issue1.reload.duplicates.include?(issue2)
368
370
369 # Closing issue 1
371 # Closing issue 1
370 issue1.init_journal(User.find(:first), "Closing issue1")
372 issue1.init_journal(User.find(:first), "Closing issue1")
371 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
373 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
372 assert issue1.save
374 assert issue1.save
373 # 2 and 3 should be also closed
375 # 2 and 3 should be also closed
374 assert issue2.reload.closed?
376 assert issue2.reload.closed?
375 assert issue3.reload.closed?
377 assert issue3.reload.closed?
376 end
378 end
377
379
378 def test_should_not_close_duplicated_issue
380 def test_should_not_close_duplicated_issue
379 # Create 3 issues
381 # Create 3 issues
380 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
382 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
381 :status_id => 1, :priority => IssuePriority.all.first,
383 :status_id => 1, :priority => IssuePriority.all.first,
382 :subject => 'Duplicates test', :description => 'Duplicates test')
384 :subject => 'Duplicates test', :description => 'Duplicates test')
383 assert issue1.save
385 assert issue1.save
384 issue2 = issue1.clone
386 issue2 = issue1.clone
385 assert issue2.save
387 assert issue2.save
386
388
387 # 2 is a dupe of 1
389 # 2 is a dupe of 1
388 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
390 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
389 # 2 is a dup of 1 but 1 is not a duplicate of 2
391 # 2 is a dup of 1 but 1 is not a duplicate of 2
390 assert !issue2.reload.duplicates.include?(issue1)
392 assert !issue2.reload.duplicates.include?(issue1)
391
393
392 # Closing issue 2
394 # Closing issue 2
393 issue2.init_journal(User.find(:first), "Closing issue2")
395 issue2.init_journal(User.find(:first), "Closing issue2")
394 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
396 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
395 assert issue2.save
397 assert issue2.save
396 # 1 should not be also closed
398 # 1 should not be also closed
397 assert !issue1.reload.closed?
399 assert !issue1.reload.closed?
398 end
400 end
399
401
400 def test_assignable_versions
402 def test_assignable_versions
401 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
403 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
402 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
404 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
403 end
405 end
404
406
405 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
407 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
406 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
408 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
407 assert !issue.save
409 assert !issue.save
408 assert_not_nil issue.errors.on(:fixed_version_id)
410 assert_not_nil issue.errors.on(:fixed_version_id)
409 end
411 end
410
412
411 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
413 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
412 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
414 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
413 assert !issue.save
415 assert !issue.save
414 assert_not_nil issue.errors.on(:fixed_version_id)
416 assert_not_nil issue.errors.on(:fixed_version_id)
415 end
417 end
416
418
417 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
419 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
418 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
420 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
419 assert issue.save
421 assert issue.save
420 end
422 end
421
423
422 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
424 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
423 issue = Issue.find(11)
425 issue = Issue.find(11)
424 assert_equal 'closed', issue.fixed_version.status
426 assert_equal 'closed', issue.fixed_version.status
425 issue.subject = 'Subject changed'
427 issue.subject = 'Subject changed'
426 assert issue.save
428 assert issue.save
427 end
429 end
428
430
429 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
431 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
430 issue = Issue.find(11)
432 issue = Issue.find(11)
431 issue.status_id = 1
433 issue.status_id = 1
432 assert !issue.save
434 assert !issue.save
433 assert_not_nil issue.errors.on_base
435 assert_not_nil issue.errors.on_base
434 end
436 end
435
437
436 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
438 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
437 issue = Issue.find(11)
439 issue = Issue.find(11)
438 issue.status_id = 1
440 issue.status_id = 1
439 issue.fixed_version_id = 3
441 issue.fixed_version_id = 3
440 assert issue.save
442 assert issue.save
441 end
443 end
442
444
443 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
445 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
444 issue = Issue.find(12)
446 issue = Issue.find(12)
445 assert_equal 'locked', issue.fixed_version.status
447 assert_equal 'locked', issue.fixed_version.status
446 issue.status_id = 1
448 issue.status_id = 1
447 assert issue.save
449 assert issue.save
448 end
450 end
449
451
450 def test_move_to_another_project_with_same_category
452 def test_move_to_another_project_with_same_category
451 issue = Issue.find(1)
453 issue = Issue.find(1)
452 assert issue.move_to_project(Project.find(2))
454 assert issue.move_to_project(Project.find(2))
453 issue.reload
455 issue.reload
454 assert_equal 2, issue.project_id
456 assert_equal 2, issue.project_id
455 # Category changes
457 # Category changes
456 assert_equal 4, issue.category_id
458 assert_equal 4, issue.category_id
457 # Make sure time entries were move to the target project
459 # Make sure time entries were move to the target project
458 assert_equal 2, issue.time_entries.first.project_id
460 assert_equal 2, issue.time_entries.first.project_id
459 end
461 end
460
462
461 def test_move_to_another_project_without_same_category
463 def test_move_to_another_project_without_same_category
462 issue = Issue.find(2)
464 issue = Issue.find(2)
463 assert issue.move_to_project(Project.find(2))
465 assert issue.move_to_project(Project.find(2))
464 issue.reload
466 issue.reload
465 assert_equal 2, issue.project_id
467 assert_equal 2, issue.project_id
466 # Category cleared
468 # Category cleared
467 assert_nil issue.category_id
469 assert_nil issue.category_id
468 end
470 end
469
471
470 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
472 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
471 issue = Issue.find(1)
473 issue = Issue.find(1)
472 issue.update_attribute(:fixed_version_id, 1)
474 issue.update_attribute(:fixed_version_id, 1)
473 assert issue.move_to_project(Project.find(2))
475 assert issue.move_to_project(Project.find(2))
474 issue.reload
476 issue.reload
475 assert_equal 2, issue.project_id
477 assert_equal 2, issue.project_id
476 # Cleared fixed_version
478 # Cleared fixed_version
477 assert_equal nil, issue.fixed_version
479 assert_equal nil, issue.fixed_version
478 end
480 end
479
481
480 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
482 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
481 issue = Issue.find(1)
483 issue = Issue.find(1)
482 issue.update_attribute(:fixed_version_id, 4)
484 issue.update_attribute(:fixed_version_id, 4)
483 assert issue.move_to_project(Project.find(5))
485 assert issue.move_to_project(Project.find(5))
484 issue.reload
486 issue.reload
485 assert_equal 5, issue.project_id
487 assert_equal 5, issue.project_id
486 # Keep fixed_version
488 # Keep fixed_version
487 assert_equal 4, issue.fixed_version_id
489 assert_equal 4, issue.fixed_version_id
488 end
490 end
489
491
490 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
492 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
491 issue = Issue.find(1)
493 issue = Issue.find(1)
492 issue.update_attribute(:fixed_version_id, 1)
494 issue.update_attribute(:fixed_version_id, 1)
493 assert issue.move_to_project(Project.find(5))
495 assert issue.move_to_project(Project.find(5))
494 issue.reload
496 issue.reload
495 assert_equal 5, issue.project_id
497 assert_equal 5, issue.project_id
496 # Cleared fixed_version
498 # Cleared fixed_version
497 assert_equal nil, issue.fixed_version
499 assert_equal nil, issue.fixed_version
498 end
500 end
499
501
500 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
502 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
501 issue = Issue.find(1)
503 issue = Issue.find(1)
502 issue.update_attribute(:fixed_version_id, 7)
504 issue.update_attribute(:fixed_version_id, 7)
503 assert issue.move_to_project(Project.find(2))
505 assert issue.move_to_project(Project.find(2))
504 issue.reload
506 issue.reload
505 assert_equal 2, issue.project_id
507 assert_equal 2, issue.project_id
506 # Keep fixed_version
508 # Keep fixed_version
507 assert_equal 7, issue.fixed_version_id
509 assert_equal 7, issue.fixed_version_id
508 end
510 end
509
511
510 def test_move_to_another_project_with_disabled_tracker
512 def test_move_to_another_project_with_disabled_tracker
511 issue = Issue.find(1)
513 issue = Issue.find(1)
512 target = Project.find(2)
514 target = Project.find(2)
513 target.tracker_ids = [3]
515 target.tracker_ids = [3]
514 target.save
516 target.save
515 assert_equal false, issue.move_to_project(target)
517 assert_equal false, issue.move_to_project(target)
516 issue.reload
518 issue.reload
517 assert_equal 1, issue.project_id
519 assert_equal 1, issue.project_id
518 end
520 end
519
521
520 def test_copy_to_the_same_project
522 def test_copy_to_the_same_project
521 issue = Issue.find(1)
523 issue = Issue.find(1)
522 copy = nil
524 copy = nil
523 assert_difference 'Issue.count' do
525 assert_difference 'Issue.count' do
524 copy = issue.move_to_project(issue.project, nil, :copy => true)
526 copy = issue.move_to_project(issue.project, nil, :copy => true)
525 end
527 end
526 assert_kind_of Issue, copy
528 assert_kind_of Issue, copy
527 assert_equal issue.project, copy.project
529 assert_equal issue.project, copy.project
528 assert_equal "125", copy.custom_value_for(2).value
530 assert_equal "125", copy.custom_value_for(2).value
529 end
531 end
530
532
531 def test_copy_to_another_project_and_tracker
533 def test_copy_to_another_project_and_tracker
532 issue = Issue.find(1)
534 issue = Issue.find(1)
533 copy = nil
535 copy = nil
534 assert_difference 'Issue.count' do
536 assert_difference 'Issue.count' do
535 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
537 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
536 end
538 end
537 copy.reload
539 copy.reload
538 assert_kind_of Issue, copy
540 assert_kind_of Issue, copy
539 assert_equal Project.find(3), copy.project
541 assert_equal Project.find(3), copy.project
540 assert_equal Tracker.find(2), copy.tracker
542 assert_equal Tracker.find(2), copy.tracker
541 # Custom field #2 is not associated with target tracker
543 # Custom field #2 is not associated with target tracker
542 assert_nil copy.custom_value_for(2)
544 assert_nil copy.custom_value_for(2)
543 end
545 end
544
546
545 context "#move_to_project" do
547 context "#move_to_project" do
546 context "as a copy" do
548 context "as a copy" do
547 setup do
549 setup do
548 @issue = Issue.find(1)
550 @issue = Issue.find(1)
549 @copy = nil
551 @copy = nil
550 end
552 end
551
553
552 should "not create a journal" do
554 should "not create a journal" do
553 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
555 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
554 assert_equal 0, @copy.reload.journals.size
556 assert_equal 0, @copy.reload.journals.size
555 end
557 end
556
558
557 should "allow assigned_to changes" do
559 should "allow assigned_to changes" do
558 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
560 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
559 assert_equal 3, @copy.assigned_to_id
561 assert_equal 3, @copy.assigned_to_id
560 end
562 end
561
563
562 should "allow status changes" do
564 should "allow status changes" do
563 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
565 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
564 assert_equal 2, @copy.status_id
566 assert_equal 2, @copy.status_id
565 end
567 end
566
568
567 should "allow start date changes" do
569 should "allow start date changes" do
568 date = Date.today
570 date = Date.today
569 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
571 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
570 assert_equal date, @copy.start_date
572 assert_equal date, @copy.start_date
571 end
573 end
572
574
573 should "allow due date changes" do
575 should "allow due date changes" do
574 date = Date.today
576 date = Date.today
575 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
577 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
576
578
577 assert_equal date, @copy.due_date
579 assert_equal date, @copy.due_date
578 end
580 end
579
581
580 should "set current user as author" do
582 should "set current user as author" do
581 User.current = User.find(9)
583 User.current = User.find(9)
582 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
584 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
583
585
584 assert_equal User.current, @copy.author
586 assert_equal User.current, @copy.author
585 end
587 end
586
588
587 should "keep journal notes" do
589 should "keep journal notes" do
588 date = Date.today
590 date = Date.today
589 notes = "Notes added when copying"
591 notes = "Notes added when copying"
590 User.current = User.find(9)
592 User.current = User.find(9)
591 @issue.init_journal(User.current, notes)
593 @issue.init_journal(User.current, notes)
592 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
594 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
593
595
594 assert_equal 1, @copy.journals.size
596 assert_equal 1, @copy.journals.size
595 journal = @copy.journals.first
597 journal = @copy.journals.first
596 assert_equal 0, journal.details.size
598 assert_equal 0, journal.details.size
597 assert_equal notes, journal.notes
599 assert_equal notes, journal.notes
598 end
600 end
599 end
601 end
600 end
602 end
601
603
602 def test_recipients_should_not_include_users_that_cannot_view_the_issue
604 def test_recipients_should_not_include_users_that_cannot_view_the_issue
603 issue = Issue.find(12)
605 issue = Issue.find(12)
604 assert issue.recipients.include?(issue.author.mail)
606 assert issue.recipients.include?(issue.author.mail)
605 # move the issue to a private project
607 # move the issue to a private project
606 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
608 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
607 # author is not a member of project anymore
609 # author is not a member of project anymore
608 assert !copy.recipients.include?(copy.author.mail)
610 assert !copy.recipients.include?(copy.author.mail)
609 end
611 end
610
612
611 def test_recipients_should_include_the_assigned_group_members
613 def test_recipients_should_include_the_assigned_group_members
612 group_member = User.generate_with_protected!
614 group_member = User.generate_with_protected!
613 group = Group.generate!
615 group = Group.generate!
614 group.users << group_member
616 group.users << group_member
615
617
616 issue = Issue.find(12)
618 issue = Issue.find(12)
617 issue.assigned_to = group
619 issue.assigned_to = group
618 assert issue.recipients.include?(group_member.mail)
620 assert issue.recipients.include?(group_member.mail)
619 end
621 end
620
622
621 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
623 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
622 user = User.find(3)
624 user = User.find(3)
623 issue = Issue.find(9)
625 issue = Issue.find(9)
624 Watcher.create!(:user => user, :watchable => issue)
626 Watcher.create!(:user => user, :watchable => issue)
625 assert issue.watched_by?(user)
627 assert issue.watched_by?(user)
626 assert !issue.watcher_recipients.include?(user.mail)
628 assert !issue.watcher_recipients.include?(user.mail)
627 end
629 end
628
630
629 def test_issue_destroy
631 def test_issue_destroy
630 Issue.find(1).destroy
632 Issue.find(1).destroy
631 assert_nil Issue.find_by_id(1)
633 assert_nil Issue.find_by_id(1)
632 assert_nil TimeEntry.find_by_issue_id(1)
634 assert_nil TimeEntry.find_by_issue_id(1)
633 end
635 end
634
636
635 def test_blocked
637 def test_blocked
636 blocked_issue = Issue.find(9)
638 blocked_issue = Issue.find(9)
637 blocking_issue = Issue.find(10)
639 blocking_issue = Issue.find(10)
638
640
639 assert blocked_issue.blocked?
641 assert blocked_issue.blocked?
640 assert !blocking_issue.blocked?
642 assert !blocking_issue.blocked?
641 end
643 end
642
644
643 def test_blocked_issues_dont_allow_closed_statuses
645 def test_blocked_issues_dont_allow_closed_statuses
644 blocked_issue = Issue.find(9)
646 blocked_issue = Issue.find(9)
645
647
646 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
648 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
647 assert !allowed_statuses.empty?
649 assert !allowed_statuses.empty?
648 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
650 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
649 assert closed_statuses.empty?
651 assert closed_statuses.empty?
650 end
652 end
651
653
652 def test_unblocked_issues_allow_closed_statuses
654 def test_unblocked_issues_allow_closed_statuses
653 blocking_issue = Issue.find(10)
655 blocking_issue = Issue.find(10)
654
656
655 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
657 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
656 assert !allowed_statuses.empty?
658 assert !allowed_statuses.empty?
657 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
659 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
658 assert !closed_statuses.empty?
660 assert !closed_statuses.empty?
659 end
661 end
660
662
661 def test_rescheduling_an_issue_should_reschedule_following_issue
663 def test_rescheduling_an_issue_should_reschedule_following_issue
662 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)
664 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)
663 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)
665 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)
664 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
666 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
665 assert_equal issue1.due_date + 1, issue2.reload.start_date
667 assert_equal issue1.due_date + 1, issue2.reload.start_date
666
668
667 issue1.due_date = Date.today + 5
669 issue1.due_date = Date.today + 5
668 issue1.save!
670 issue1.save!
669 assert_equal issue1.due_date + 1, issue2.reload.start_date
671 assert_equal issue1.due_date + 1, issue2.reload.start_date
670 end
672 end
671
673
672 def test_overdue
674 def test_overdue
673 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
675 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
674 assert !Issue.new(:due_date => Date.today).overdue?
676 assert !Issue.new(:due_date => Date.today).overdue?
675 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
677 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
676 assert !Issue.new(:due_date => nil).overdue?
678 assert !Issue.new(:due_date => nil).overdue?
677 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
679 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
678 end
680 end
679
681
680 context "#behind_schedule?" do
682 context "#behind_schedule?" do
681 should "be false if the issue has no start_date" do
683 should "be false if the issue has no start_date" do
682 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
684 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
683 end
685 end
684
686
685 should "be false if the issue has no end_date" do
687 should "be false if the issue has no end_date" do
686 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
688 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
687 end
689 end
688
690
689 should "be false if the issue has more done than it's calendar time" do
691 should "be false if the issue has more done than it's calendar time" do
690 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
692 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
691 end
693 end
692
694
693 should "be true if the issue hasn't been started at all" do
695 should "be true if the issue hasn't been started at all" do
694 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
696 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
695 end
697 end
696
698
697 should "be true if the issue has used more calendar time than it's done ratio" do
699 should "be true if the issue has used more calendar time than it's done ratio" do
698 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
700 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
699 end
701 end
700 end
702 end
701
703
702 context "#assignable_users" do
704 context "#assignable_users" do
703 should "be Users" do
705 should "be Users" do
704 assert_kind_of User, Issue.find(1).assignable_users.first
706 assert_kind_of User, Issue.find(1).assignable_users.first
705 end
707 end
706
708
707 should "include the issue author" do
709 should "include the issue author" do
708 project = Project.find(1)
710 project = Project.find(1)
709 non_project_member = User.generate!
711 non_project_member = User.generate!
710 issue = Issue.generate_for_project!(project, :author => non_project_member)
712 issue = Issue.generate_for_project!(project, :author => non_project_member)
711
713
712 assert issue.assignable_users.include?(non_project_member)
714 assert issue.assignable_users.include?(non_project_member)
713 end
715 end
714
716
715 should "include the current assignee" do
717 should "include the current assignee" do
716 project = Project.find(1)
718 project = Project.find(1)
717 user = User.generate!
719 user = User.generate!
718 issue = Issue.generate_for_project!(project, :assigned_to => user)
720 issue = Issue.generate_for_project!(project, :assigned_to => user)
719 user.lock!
721 user.lock!
720
722
721 assert Issue.find(issue.id).assignable_users.include?(user)
723 assert Issue.find(issue.id).assignable_users.include?(user)
722 end
724 end
723
725
724 should "not show the issue author twice" do
726 should "not show the issue author twice" do
725 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
727 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
726 assert_equal 2, assignable_user_ids.length
728 assert_equal 2, assignable_user_ids.length
727
729
728 assignable_user_ids.each do |user_id|
730 assignable_user_ids.each do |user_id|
729 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
731 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
730 end
732 end
731 end
733 end
732
734
733 context "with issue_group_assignment" do
735 context "with issue_group_assignment" do
734 should "include groups" do
736 should "include groups" do
735 issue = Issue.new(:project => Project.find(2))
737 issue = Issue.new(:project => Project.find(2))
736
738
737 with_settings :issue_group_assignment => '1' do
739 with_settings :issue_group_assignment => '1' do
738 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
740 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
739 assert issue.assignable_users.include?(Group.find(11))
741 assert issue.assignable_users.include?(Group.find(11))
740 end
742 end
741 end
743 end
742 end
744 end
743
745
744 context "without issue_group_assignment" do
746 context "without issue_group_assignment" do
745 should "not include groups" do
747 should "not include groups" do
746 issue = Issue.new(:project => Project.find(2))
748 issue = Issue.new(:project => Project.find(2))
747
749
748 with_settings :issue_group_assignment => '0' do
750 with_settings :issue_group_assignment => '0' do
749 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
751 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
750 assert !issue.assignable_users.include?(Group.find(11))
752 assert !issue.assignable_users.include?(Group.find(11))
751 end
753 end
752 end
754 end
753 end
755 end
754 end
756 end
755
757
756 def test_create_should_send_email_notification
758 def test_create_should_send_email_notification
757 ActionMailer::Base.deliveries.clear
759 ActionMailer::Base.deliveries.clear
758 issue = Issue.new(:project_id => 1, :tracker_id => 1,
760 issue = Issue.new(:project_id => 1, :tracker_id => 1,
759 :author_id => 3, :status_id => 1,
761 :author_id => 3, :status_id => 1,
760 :priority => IssuePriority.all.first,
762 :priority => IssuePriority.all.first,
761 :subject => 'test_create', :estimated_hours => '1:30')
763 :subject => 'test_create', :estimated_hours => '1:30')
762
764
763 assert issue.save
765 assert issue.save
764 assert_equal 1, ActionMailer::Base.deliveries.size
766 assert_equal 1, ActionMailer::Base.deliveries.size
765 end
767 end
766
768
767 def test_stale_issue_should_not_send_email_notification
769 def test_stale_issue_should_not_send_email_notification
768 ActionMailer::Base.deliveries.clear
770 ActionMailer::Base.deliveries.clear
769 issue = Issue.find(1)
771 issue = Issue.find(1)
770 stale = Issue.find(1)
772 stale = Issue.find(1)
771
773
772 issue.init_journal(User.find(1))
774 issue.init_journal(User.find(1))
773 issue.subject = 'Subjet update'
775 issue.subject = 'Subjet update'
774 assert issue.save
776 assert issue.save
775 assert_equal 1, ActionMailer::Base.deliveries.size
777 assert_equal 1, ActionMailer::Base.deliveries.size
776 ActionMailer::Base.deliveries.clear
778 ActionMailer::Base.deliveries.clear
777
779
778 stale.init_journal(User.find(1))
780 stale.init_journal(User.find(1))
779 stale.subject = 'Another subjet update'
781 stale.subject = 'Another subjet update'
780 assert_raise ActiveRecord::StaleObjectError do
782 assert_raise ActiveRecord::StaleObjectError do
781 stale.save
783 stale.save
782 end
784 end
783 assert ActionMailer::Base.deliveries.empty?
785 assert ActionMailer::Base.deliveries.empty?
784 end
786 end
785
787
786 def test_journalized_description
788 def test_journalized_description
787 IssueCustomField.delete_all
789 IssueCustomField.delete_all
788
790
789 i = Issue.first
791 i = Issue.first
790 old_description = i.description
792 old_description = i.description
791 new_description = "This is the new description"
793 new_description = "This is the new description"
792
794
793 i.init_journal(User.find(2))
795 i.init_journal(User.find(2))
794 i.description = new_description
796 i.description = new_description
795 assert_difference 'Journal.count', 1 do
797 assert_difference 'Journal.count', 1 do
796 assert_difference 'JournalDetail.count', 1 do
798 assert_difference 'JournalDetail.count', 1 do
797 i.save!
799 i.save!
798 end
800 end
799 end
801 end
800
802
801 detail = JournalDetail.first(:order => 'id DESC')
803 detail = JournalDetail.first(:order => 'id DESC')
802 assert_equal i, detail.journal.journalized
804 assert_equal i, detail.journal.journalized
803 assert_equal 'attr', detail.property
805 assert_equal 'attr', detail.property
804 assert_equal 'description', detail.prop_key
806 assert_equal 'description', detail.prop_key
805 assert_equal old_description, detail.old_value
807 assert_equal old_description, detail.old_value
806 assert_equal new_description, detail.value
808 assert_equal new_description, detail.value
807 end
809 end
808
810
809 def test_blank_descriptions_should_not_be_journalized
811 def test_blank_descriptions_should_not_be_journalized
810 IssueCustomField.delete_all
812 IssueCustomField.delete_all
811 Issue.update_all("description = NULL", "id=1")
813 Issue.update_all("description = NULL", "id=1")
812
814
813 i = Issue.find(1)
815 i = Issue.find(1)
814 i.init_journal(User.find(2))
816 i.init_journal(User.find(2))
815 i.subject = "blank description"
817 i.subject = "blank description"
816 i.description = "\r\n"
818 i.description = "\r\n"
817
819
818 assert_difference 'Journal.count', 1 do
820 assert_difference 'Journal.count', 1 do
819 assert_difference 'JournalDetail.count', 1 do
821 assert_difference 'JournalDetail.count', 1 do
820 i.save!
822 i.save!
821 end
823 end
822 end
824 end
823 end
825 end
824
826
825 def test_description_eol_should_be_normalized
827 def test_description_eol_should_be_normalized
826 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
828 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
827 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
829 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
828 end
830 end
829
831
830 def test_saving_twice_should_not_duplicate_journal_details
832 def test_saving_twice_should_not_duplicate_journal_details
831 i = Issue.find(:first)
833 i = Issue.find(:first)
832 i.init_journal(User.find(2), 'Some notes')
834 i.init_journal(User.find(2), 'Some notes')
833 # initial changes
835 # initial changes
834 i.subject = 'New subject'
836 i.subject = 'New subject'
835 i.done_ratio = i.done_ratio + 10
837 i.done_ratio = i.done_ratio + 10
836 assert_difference 'Journal.count' do
838 assert_difference 'Journal.count' do
837 assert i.save
839 assert i.save
838 end
840 end
839 # 1 more change
841 # 1 more change
840 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
842 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
841 assert_no_difference 'Journal.count' do
843 assert_no_difference 'Journal.count' do
842 assert_difference 'JournalDetail.count', 1 do
844 assert_difference 'JournalDetail.count', 1 do
843 i.save
845 i.save
844 end
846 end
845 end
847 end
846 # no more change
848 # no more change
847 assert_no_difference 'Journal.count' do
849 assert_no_difference 'Journal.count' do
848 assert_no_difference 'JournalDetail.count' do
850 assert_no_difference 'JournalDetail.count' do
849 i.save
851 i.save
850 end
852 end
851 end
853 end
852 end
854 end
853
855
854 def test_all_dependent_issues
856 def test_all_dependent_issues
855 IssueRelation.delete_all
857 IssueRelation.delete_all
856 assert IssueRelation.create!(:issue_from => Issue.find(1),
858 assert IssueRelation.create!(:issue_from => Issue.find(1),
857 :issue_to => Issue.find(2),
859 :issue_to => Issue.find(2),
858 :relation_type => IssueRelation::TYPE_PRECEDES)
860 :relation_type => IssueRelation::TYPE_PRECEDES)
859 assert IssueRelation.create!(:issue_from => Issue.find(2),
861 assert IssueRelation.create!(:issue_from => Issue.find(2),
860 :issue_to => Issue.find(3),
862 :issue_to => Issue.find(3),
861 :relation_type => IssueRelation::TYPE_PRECEDES)
863 :relation_type => IssueRelation::TYPE_PRECEDES)
862 assert IssueRelation.create!(:issue_from => Issue.find(3),
864 assert IssueRelation.create!(:issue_from => Issue.find(3),
863 :issue_to => Issue.find(8),
865 :issue_to => Issue.find(8),
864 :relation_type => IssueRelation::TYPE_PRECEDES)
866 :relation_type => IssueRelation::TYPE_PRECEDES)
865
867
866 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
868 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
867 end
869 end
868
870
869 def test_all_dependent_issues_with_persistent_circular_dependency
871 def test_all_dependent_issues_with_persistent_circular_dependency
870 IssueRelation.delete_all
872 IssueRelation.delete_all
871 assert IssueRelation.create!(:issue_from => Issue.find(1),
873 assert IssueRelation.create!(:issue_from => Issue.find(1),
872 :issue_to => Issue.find(2),
874 :issue_to => Issue.find(2),
873 :relation_type => IssueRelation::TYPE_PRECEDES)
875 :relation_type => IssueRelation::TYPE_PRECEDES)
874 assert IssueRelation.create!(:issue_from => Issue.find(2),
876 assert IssueRelation.create!(:issue_from => Issue.find(2),
875 :issue_to => Issue.find(3),
877 :issue_to => Issue.find(3),
876 :relation_type => IssueRelation::TYPE_PRECEDES)
878 :relation_type => IssueRelation::TYPE_PRECEDES)
877 # Validation skipping
879 # Validation skipping
878 assert IssueRelation.new(:issue_from => Issue.find(3),
880 assert IssueRelation.new(:issue_from => Issue.find(3),
879 :issue_to => Issue.find(1),
881 :issue_to => Issue.find(1),
880 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
882 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
881
883
882 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
884 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
883 end
885 end
884
886
885 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
887 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
886 IssueRelation.delete_all
888 IssueRelation.delete_all
887 assert IssueRelation.create!(:issue_from => Issue.find(1),
889 assert IssueRelation.create!(:issue_from => Issue.find(1),
888 :issue_to => Issue.find(2),
890 :issue_to => Issue.find(2),
889 :relation_type => IssueRelation::TYPE_RELATES)
891 :relation_type => IssueRelation::TYPE_RELATES)
890 assert IssueRelation.create!(:issue_from => Issue.find(2),
892 assert IssueRelation.create!(:issue_from => Issue.find(2),
891 :issue_to => Issue.find(3),
893 :issue_to => Issue.find(3),
892 :relation_type => IssueRelation::TYPE_RELATES)
894 :relation_type => IssueRelation::TYPE_RELATES)
893 assert IssueRelation.create!(:issue_from => Issue.find(3),
895 assert IssueRelation.create!(:issue_from => Issue.find(3),
894 :issue_to => Issue.find(8),
896 :issue_to => Issue.find(8),
895 :relation_type => IssueRelation::TYPE_RELATES)
897 :relation_type => IssueRelation::TYPE_RELATES)
896 # Validation skipping
898 # Validation skipping
897 assert IssueRelation.new(:issue_from => Issue.find(8),
899 assert IssueRelation.new(:issue_from => Issue.find(8),
898 :issue_to => Issue.find(2),
900 :issue_to => Issue.find(2),
899 :relation_type => IssueRelation::TYPE_RELATES).save(false)
901 :relation_type => IssueRelation::TYPE_RELATES).save(false)
900 assert IssueRelation.new(:issue_from => Issue.find(3),
902 assert IssueRelation.new(:issue_from => Issue.find(3),
901 :issue_to => Issue.find(1),
903 :issue_to => Issue.find(1),
902 :relation_type => IssueRelation::TYPE_RELATES).save(false)
904 :relation_type => IssueRelation::TYPE_RELATES).save(false)
903
905
904 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
906 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
905 end
907 end
906
908
907 context "#done_ratio" do
909 context "#done_ratio" do
908 setup do
910 setup do
909 @issue = Issue.find(1)
911 @issue = Issue.find(1)
910 @issue_status = IssueStatus.find(1)
912 @issue_status = IssueStatus.find(1)
911 @issue_status.update_attribute(:default_done_ratio, 50)
913 @issue_status.update_attribute(:default_done_ratio, 50)
912 @issue2 = Issue.find(2)
914 @issue2 = Issue.find(2)
913 @issue_status2 = IssueStatus.find(2)
915 @issue_status2 = IssueStatus.find(2)
914 @issue_status2.update_attribute(:default_done_ratio, 0)
916 @issue_status2.update_attribute(:default_done_ratio, 0)
915 end
917 end
916
918
917 context "with Setting.issue_done_ratio using the issue_field" do
919 context "with Setting.issue_done_ratio using the issue_field" do
918 setup do
920 setup do
919 Setting.issue_done_ratio = 'issue_field'
921 Setting.issue_done_ratio = 'issue_field'
920 end
922 end
921
923
922 should "read the issue's field" do
924 should "read the issue's field" do
923 assert_equal 0, @issue.done_ratio
925 assert_equal 0, @issue.done_ratio
924 assert_equal 30, @issue2.done_ratio
926 assert_equal 30, @issue2.done_ratio
925 end
927 end
926 end
928 end
927
929
928 context "with Setting.issue_done_ratio using the issue_status" do
930 context "with Setting.issue_done_ratio using the issue_status" do
929 setup do
931 setup do
930 Setting.issue_done_ratio = 'issue_status'
932 Setting.issue_done_ratio = 'issue_status'
931 end
933 end
932
934
933 should "read the Issue Status's default done ratio" do
935 should "read the Issue Status's default done ratio" do
934 assert_equal 50, @issue.done_ratio
936 assert_equal 50, @issue.done_ratio
935 assert_equal 0, @issue2.done_ratio
937 assert_equal 0, @issue2.done_ratio
936 end
938 end
937 end
939 end
938 end
940 end
939
941
940 context "#update_done_ratio_from_issue_status" do
942 context "#update_done_ratio_from_issue_status" do
941 setup do
943 setup do
942 @issue = Issue.find(1)
944 @issue = Issue.find(1)
943 @issue_status = IssueStatus.find(1)
945 @issue_status = IssueStatus.find(1)
944 @issue_status.update_attribute(:default_done_ratio, 50)
946 @issue_status.update_attribute(:default_done_ratio, 50)
945 @issue2 = Issue.find(2)
947 @issue2 = Issue.find(2)
946 @issue_status2 = IssueStatus.find(2)
948 @issue_status2 = IssueStatus.find(2)
947 @issue_status2.update_attribute(:default_done_ratio, 0)
949 @issue_status2.update_attribute(:default_done_ratio, 0)
948 end
950 end
949
951
950 context "with Setting.issue_done_ratio using the issue_field" do
952 context "with Setting.issue_done_ratio using the issue_field" do
951 setup do
953 setup do
952 Setting.issue_done_ratio = 'issue_field'
954 Setting.issue_done_ratio = 'issue_field'
953 end
955 end
954
956
955 should "not change the issue" do
957 should "not change the issue" do
956 @issue.update_done_ratio_from_issue_status
958 @issue.update_done_ratio_from_issue_status
957 @issue2.update_done_ratio_from_issue_status
959 @issue2.update_done_ratio_from_issue_status
958
960
959 assert_equal 0, @issue.read_attribute(:done_ratio)
961 assert_equal 0, @issue.read_attribute(:done_ratio)
960 assert_equal 30, @issue2.read_attribute(:done_ratio)
962 assert_equal 30, @issue2.read_attribute(:done_ratio)
961 end
963 end
962 end
964 end
963
965
964 context "with Setting.issue_done_ratio using the issue_status" do
966 context "with Setting.issue_done_ratio using the issue_status" do
965 setup do
967 setup do
966 Setting.issue_done_ratio = 'issue_status'
968 Setting.issue_done_ratio = 'issue_status'
967 end
969 end
968
970
969 should "change the issue's done ratio" do
971 should "change the issue's done ratio" do
970 @issue.update_done_ratio_from_issue_status
972 @issue.update_done_ratio_from_issue_status
971 @issue2.update_done_ratio_from_issue_status
973 @issue2.update_done_ratio_from_issue_status
972
974
973 assert_equal 50, @issue.read_attribute(:done_ratio)
975 assert_equal 50, @issue.read_attribute(:done_ratio)
974 assert_equal 0, @issue2.read_attribute(:done_ratio)
976 assert_equal 0, @issue2.read_attribute(:done_ratio)
975 end
977 end
976 end
978 end
977 end
979 end
978
980
979 test "#by_tracker" do
981 test "#by_tracker" do
980 User.current = User.anonymous
982 User.current = User.anonymous
981 groups = Issue.by_tracker(Project.find(1))
983 groups = Issue.by_tracker(Project.find(1))
982 assert_equal 3, groups.size
984 assert_equal 3, groups.size
983 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
985 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
984 end
986 end
985
987
986 test "#by_version" do
988 test "#by_version" do
987 User.current = User.anonymous
989 User.current = User.anonymous
988 groups = Issue.by_version(Project.find(1))
990 groups = Issue.by_version(Project.find(1))
989 assert_equal 3, groups.size
991 assert_equal 3, groups.size
990 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
992 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
991 end
993 end
992
994
993 test "#by_priority" do
995 test "#by_priority" do
994 User.current = User.anonymous
996 User.current = User.anonymous
995 groups = Issue.by_priority(Project.find(1))
997 groups = Issue.by_priority(Project.find(1))
996 assert_equal 4, groups.size
998 assert_equal 4, groups.size
997 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
999 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
998 end
1000 end
999
1001
1000 test "#by_category" do
1002 test "#by_category" do
1001 User.current = User.anonymous
1003 User.current = User.anonymous
1002 groups = Issue.by_category(Project.find(1))
1004 groups = Issue.by_category(Project.find(1))
1003 assert_equal 2, groups.size
1005 assert_equal 2, groups.size
1004 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1006 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1005 end
1007 end
1006
1008
1007 test "#by_assigned_to" do
1009 test "#by_assigned_to" do
1008 User.current = User.anonymous
1010 User.current = User.anonymous
1009 groups = Issue.by_assigned_to(Project.find(1))
1011 groups = Issue.by_assigned_to(Project.find(1))
1010 assert_equal 2, groups.size
1012 assert_equal 2, groups.size
1011 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1013 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1012 end
1014 end
1013
1015
1014 test "#by_author" do
1016 test "#by_author" do
1015 User.current = User.anonymous
1017 User.current = User.anonymous
1016 groups = Issue.by_author(Project.find(1))
1018 groups = Issue.by_author(Project.find(1))
1017 assert_equal 4, groups.size
1019 assert_equal 4, groups.size
1018 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1020 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1019 end
1021 end
1020
1022
1021 test "#by_subproject" do
1023 test "#by_subproject" do
1022 User.current = User.anonymous
1024 User.current = User.anonymous
1023 groups = Issue.by_subproject(Project.find(1))
1025 groups = Issue.by_subproject(Project.find(1))
1024 # Private descendant not visible
1026 # Private descendant not visible
1025 assert_equal 1, groups.size
1027 assert_equal 1, groups.size
1026 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1028 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1027 end
1029 end
1028
1030
1029 context ".allowed_target_projects_on_move" do
1031 context ".allowed_target_projects_on_move" do
1030 should "return all active projects for admin users" do
1032 should "return all active projects for admin users" do
1031 User.current = User.find(1)
1033 User.current = User.find(1)
1032 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1034 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1033 end
1035 end
1034
1036
1035 should "return allowed projects for non admin users" do
1037 should "return allowed projects for non admin users" do
1036 User.current = User.find(2)
1038 User.current = User.find(2)
1037 Role.non_member.remove_permission! :move_issues
1039 Role.non_member.remove_permission! :move_issues
1038 assert_equal 3, Issue.allowed_target_projects_on_move.size
1040 assert_equal 3, Issue.allowed_target_projects_on_move.size
1039
1041
1040 Role.non_member.add_permission! :move_issues
1042 Role.non_member.add_permission! :move_issues
1041 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1043 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1042 end
1044 end
1043 end
1045 end
1044
1046
1045 def test_recently_updated_with_limit_scopes
1047 def test_recently_updated_with_limit_scopes
1046 #should return the last updated issue
1048 #should return the last updated issue
1047 assert_equal 1, Issue.recently_updated.with_limit(1).length
1049 assert_equal 1, Issue.recently_updated.with_limit(1).length
1048 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1050 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1049 end
1051 end
1050
1052
1051 def test_on_active_projects_scope
1053 def test_on_active_projects_scope
1052 assert Project.find(2).archive
1054 assert Project.find(2).archive
1053
1055
1054 before = Issue.on_active_project.length
1056 before = Issue.on_active_project.length
1055 # test inclusion to results
1057 # test inclusion to results
1056 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1058 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1057 assert_equal before + 1, Issue.on_active_project.length
1059 assert_equal before + 1, Issue.on_active_project.length
1058
1060
1059 # Move to an archived project
1061 # Move to an archived project
1060 issue.project = Project.find(2)
1062 issue.project = Project.find(2)
1061 assert issue.save
1063 assert issue.save
1062 assert_equal before, Issue.on_active_project.length
1064 assert_equal before, Issue.on_active_project.length
1063 end
1065 end
1064
1066
1065 context "Issue#recipients" do
1067 context "Issue#recipients" do
1066 setup do
1068 setup do
1067 @project = Project.find(1)
1069 @project = Project.find(1)
1068 @author = User.generate_with_protected!
1070 @author = User.generate_with_protected!
1069 @assignee = User.generate_with_protected!
1071 @assignee = User.generate_with_protected!
1070 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1072 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1071 end
1073 end
1072
1074
1073 should "include project recipients" do
1075 should "include project recipients" do
1074 assert @project.recipients.present?
1076 assert @project.recipients.present?
1075 @project.recipients.each do |project_recipient|
1077 @project.recipients.each do |project_recipient|
1076 assert @issue.recipients.include?(project_recipient)
1078 assert @issue.recipients.include?(project_recipient)
1077 end
1079 end
1078 end
1080 end
1079
1081
1080 should "include the author if the author is active" do
1082 should "include the author if the author is active" do
1081 assert @issue.author, "No author set for Issue"
1083 assert @issue.author, "No author set for Issue"
1082 assert @issue.recipients.include?(@issue.author.mail)
1084 assert @issue.recipients.include?(@issue.author.mail)
1083 end
1085 end
1084
1086
1085 should "include the assigned to user if the assigned to user is active" do
1087 should "include the assigned to user if the assigned to user is active" do
1086 assert @issue.assigned_to, "No assigned_to set for Issue"
1088 assert @issue.assigned_to, "No assigned_to set for Issue"
1087 assert @issue.recipients.include?(@issue.assigned_to.mail)
1089 assert @issue.recipients.include?(@issue.assigned_to.mail)
1088 end
1090 end
1089
1091
1090 should "not include users who opt out of all email" do
1092 should "not include users who opt out of all email" do
1091 @author.update_attribute(:mail_notification, :none)
1093 @author.update_attribute(:mail_notification, :none)
1092
1094
1093 assert !@issue.recipients.include?(@issue.author.mail)
1095 assert !@issue.recipients.include?(@issue.author.mail)
1094 end
1096 end
1095
1097
1096 should "not include the issue author if they are only notified of assigned issues" do
1098 should "not include the issue author if they are only notified of assigned issues" do
1097 @author.update_attribute(:mail_notification, :only_assigned)
1099 @author.update_attribute(:mail_notification, :only_assigned)
1098
1100
1099 assert !@issue.recipients.include?(@issue.author.mail)
1101 assert !@issue.recipients.include?(@issue.author.mail)
1100 end
1102 end
1101
1103
1102 should "not include the assigned user if they are only notified of owned issues" do
1104 should "not include the assigned user if they are only notified of owned issues" do
1103 @assignee.update_attribute(:mail_notification, :only_owner)
1105 @assignee.update_attribute(:mail_notification, :only_owner)
1104
1106
1105 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1107 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1106 end
1108 end
1107
1109
1108 end
1110 end
1109 end
1111 end
General Comments 0
You need to be logged in to leave comments. Login now