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