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