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