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