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