##// END OF EJS Templates
add test not to send mail with no settng in creating issue (#15612)...
Toshi MARUYAMA -
r12107:b212fdb72b65
parent child
Show More
@@ -1,2293 +1,2305
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2013 Jean-Philippe Lang
2 # Copyright (C) 2006-2013 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 :groups_users,
22 :groups_users,
23 :trackers, :projects_trackers,
23 :trackers, :projects_trackers,
24 :enabled_modules,
24 :enabled_modules,
25 :versions,
25 :versions,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
27 :enumerations,
27 :enumerations,
28 :issues, :journals, :journal_details,
28 :issues, :journals, :journal_details,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
30 :time_entries
30 :time_entries
31
31
32 include Redmine::I18n
32 include Redmine::I18n
33
33
34 def teardown
34 def teardown
35 User.current = nil
35 User.current = nil
36 end
36 end
37
37
38 def test_initialize
38 def test_initialize
39 issue = Issue.new
39 issue = Issue.new
40
40
41 assert_nil issue.project_id
41 assert_nil issue.project_id
42 assert_nil issue.tracker_id
42 assert_nil issue.tracker_id
43 assert_nil issue.author_id
43 assert_nil issue.author_id
44 assert_nil issue.assigned_to_id
44 assert_nil issue.assigned_to_id
45 assert_nil issue.category_id
45 assert_nil issue.category_id
46
46
47 assert_equal IssueStatus.default, issue.status
47 assert_equal IssueStatus.default, issue.status
48 assert_equal IssuePriority.default, issue.priority
48 assert_equal IssuePriority.default, issue.priority
49 end
49 end
50
50
51 def test_create
51 def test_create
52 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
52 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
53 :status_id => 1, :priority => IssuePriority.all.first,
53 :status_id => 1, :priority => IssuePriority.all.first,
54 :subject => 'test_create',
54 :subject => 'test_create',
55 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
55 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
56 assert issue.save
56 assert issue.save
57 issue.reload
57 issue.reload
58 assert_equal 1.5, issue.estimated_hours
58 assert_equal 1.5, issue.estimated_hours
59 end
59 end
60
60
61 def test_create_minimal
61 def test_create_minimal
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
63 :status_id => 1, :priority => IssuePriority.all.first,
63 :status_id => 1, :priority => IssuePriority.all.first,
64 :subject => 'test_create')
64 :subject => 'test_create')
65 assert issue.save
65 assert issue.save
66 assert issue.description.nil?
66 assert issue.description.nil?
67 assert_nil issue.estimated_hours
67 assert_nil issue.estimated_hours
68 end
68 end
69
69
70 def test_start_date_format_should_be_validated
70 def test_start_date_format_should_be_validated
71 set_language_if_valid 'en'
71 set_language_if_valid 'en'
72 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
72 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
73 issue = Issue.new(:start_date => invalid_date)
73 issue = Issue.new(:start_date => invalid_date)
74 assert !issue.valid?
74 assert !issue.valid?
75 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
75 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
76 end
76 end
77 end
77 end
78
78
79 def test_due_date_format_should_be_validated
79 def test_due_date_format_should_be_validated
80 set_language_if_valid 'en'
80 set_language_if_valid 'en'
81 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
81 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
82 issue = Issue.new(:due_date => invalid_date)
82 issue = Issue.new(:due_date => invalid_date)
83 assert !issue.valid?
83 assert !issue.valid?
84 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
84 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
85 end
85 end
86 end
86 end
87
87
88 def test_due_date_lesser_than_start_date_should_not_validate
88 def test_due_date_lesser_than_start_date_should_not_validate
89 set_language_if_valid 'en'
89 set_language_if_valid 'en'
90 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
90 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
91 assert !issue.valid?
91 assert !issue.valid?
92 assert_include 'Due date must be greater than start date', issue.errors.full_messages
92 assert_include 'Due date must be greater than start date', issue.errors.full_messages
93 end
93 end
94
94
95 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
95 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
96 issue = Issue.generate(:start_date => '2013-06-04')
96 issue = Issue.generate(:start_date => '2013-06-04')
97 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
97 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
98 assert !issue.valid?
98 assert !issue.valid?
99 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
99 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
100 end
100 end
101
101
102 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
102 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
103 issue = Issue.generate!(:start_date => '2013-06-04')
103 issue = Issue.generate!(:start_date => '2013-06-04')
104 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
104 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
105 issue.start_date = '2013-06-07'
105 issue.start_date = '2013-06-07'
106 assert !issue.valid?
106 assert !issue.valid?
107 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
107 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
108 end
108 end
109
109
110 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
110 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
111 issue = Issue.generate!(:start_date => '2013-06-04')
111 issue = Issue.generate!(:start_date => '2013-06-04')
112 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
112 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
113 assert issue.valid?
113 assert issue.valid?
114 end
114 end
115
115
116 def test_estimated_hours_should_be_validated
116 def test_estimated_hours_should_be_validated
117 set_language_if_valid 'en'
117 set_language_if_valid 'en'
118 ['-2'].each do |invalid|
118 ['-2'].each do |invalid|
119 issue = Issue.new(:estimated_hours => invalid)
119 issue = Issue.new(:estimated_hours => invalid)
120 assert !issue.valid?
120 assert !issue.valid?
121 assert_include 'Estimated time is invalid', issue.errors.full_messages
121 assert_include 'Estimated time is invalid', issue.errors.full_messages
122 end
122 end
123 end
123 end
124
124
125 def test_create_with_required_custom_field
125 def test_create_with_required_custom_field
126 set_language_if_valid 'en'
126 set_language_if_valid 'en'
127 field = IssueCustomField.find_by_name('Database')
127 field = IssueCustomField.find_by_name('Database')
128 field.update_attribute(:is_required, true)
128 field.update_attribute(:is_required, true)
129
129
130 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
130 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
131 :status_id => 1, :subject => 'test_create',
131 :status_id => 1, :subject => 'test_create',
132 :description => 'IssueTest#test_create_with_required_custom_field')
132 :description => 'IssueTest#test_create_with_required_custom_field')
133 assert issue.available_custom_fields.include?(field)
133 assert issue.available_custom_fields.include?(field)
134 # No value for the custom field
134 # No value for the custom field
135 assert !issue.save
135 assert !issue.save
136 assert_equal ["Database can't be blank"], issue.errors.full_messages
136 assert_equal ["Database can't be blank"], issue.errors.full_messages
137 # Blank value
137 # Blank value
138 issue.custom_field_values = { field.id => '' }
138 issue.custom_field_values = { field.id => '' }
139 assert !issue.save
139 assert !issue.save
140 assert_equal ["Database can't be blank"], issue.errors.full_messages
140 assert_equal ["Database can't be blank"], issue.errors.full_messages
141 # Invalid value
141 # Invalid value
142 issue.custom_field_values = { field.id => 'SQLServer' }
142 issue.custom_field_values = { field.id => 'SQLServer' }
143 assert !issue.save
143 assert !issue.save
144 assert_equal ["Database is not included in the list"], issue.errors.full_messages
144 assert_equal ["Database is not included in the list"], issue.errors.full_messages
145 # Valid value
145 # Valid value
146 issue.custom_field_values = { field.id => 'PostgreSQL' }
146 issue.custom_field_values = { field.id => 'PostgreSQL' }
147 assert issue.save
147 assert issue.save
148 issue.reload
148 issue.reload
149 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
149 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
150 end
150 end
151
151
152 def test_create_with_group_assignment
152 def test_create_with_group_assignment
153 with_settings :issue_group_assignment => '1' do
153 with_settings :issue_group_assignment => '1' do
154 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
154 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
155 :subject => 'Group assignment',
155 :subject => 'Group assignment',
156 :assigned_to_id => 11).save
156 :assigned_to_id => 11).save
157 issue = Issue.first(:order => 'id DESC')
157 issue = Issue.first(:order => 'id DESC')
158 assert_kind_of Group, issue.assigned_to
158 assert_kind_of Group, issue.assigned_to
159 assert_equal Group.find(11), issue.assigned_to
159 assert_equal Group.find(11), issue.assigned_to
160 end
160 end
161 end
161 end
162
162
163 def test_create_with_parent_issue_id
163 def test_create_with_parent_issue_id
164 issue = Issue.new(:project_id => 1, :tracker_id => 1,
164 issue = Issue.new(:project_id => 1, :tracker_id => 1,
165 :author_id => 1, :subject => 'Group assignment',
165 :author_id => 1, :subject => 'Group assignment',
166 :parent_issue_id => 1)
166 :parent_issue_id => 1)
167 assert_save issue
167 assert_save issue
168 assert_equal 1, issue.parent_issue_id
168 assert_equal 1, issue.parent_issue_id
169 assert_equal Issue.find(1), issue.parent
169 assert_equal Issue.find(1), issue.parent
170 end
170 end
171
171
172 def test_create_with_sharp_parent_issue_id
172 def test_create_with_sharp_parent_issue_id
173 issue = Issue.new(:project_id => 1, :tracker_id => 1,
173 issue = Issue.new(:project_id => 1, :tracker_id => 1,
174 :author_id => 1, :subject => 'Group assignment',
174 :author_id => 1, :subject => 'Group assignment',
175 :parent_issue_id => "#1")
175 :parent_issue_id => "#1")
176 assert_save issue
176 assert_save issue
177 assert_equal 1, issue.parent_issue_id
177 assert_equal 1, issue.parent_issue_id
178 assert_equal Issue.find(1), issue.parent
178 assert_equal Issue.find(1), issue.parent
179 end
179 end
180
180
181 def test_create_with_invalid_parent_issue_id
181 def test_create_with_invalid_parent_issue_id
182 set_language_if_valid 'en'
182 set_language_if_valid 'en'
183 issue = Issue.new(:project_id => 1, :tracker_id => 1,
183 issue = Issue.new(:project_id => 1, :tracker_id => 1,
184 :author_id => 1, :subject => 'Group assignment',
184 :author_id => 1, :subject => 'Group assignment',
185 :parent_issue_id => '01ABC')
185 :parent_issue_id => '01ABC')
186 assert !issue.save
186 assert !issue.save
187 assert_equal '01ABC', issue.parent_issue_id
187 assert_equal '01ABC', issue.parent_issue_id
188 assert_include 'Parent task is invalid', issue.errors.full_messages
188 assert_include 'Parent task is invalid', issue.errors.full_messages
189 end
189 end
190
190
191 def test_create_with_invalid_sharp_parent_issue_id
191 def test_create_with_invalid_sharp_parent_issue_id
192 set_language_if_valid 'en'
192 set_language_if_valid 'en'
193 issue = Issue.new(:project_id => 1, :tracker_id => 1,
193 issue = Issue.new(:project_id => 1, :tracker_id => 1,
194 :author_id => 1, :subject => 'Group assignment',
194 :author_id => 1, :subject => 'Group assignment',
195 :parent_issue_id => '#01ABC')
195 :parent_issue_id => '#01ABC')
196 assert !issue.save
196 assert !issue.save
197 assert_equal '#01ABC', issue.parent_issue_id
197 assert_equal '#01ABC', issue.parent_issue_id
198 assert_include 'Parent task is invalid', issue.errors.full_messages
198 assert_include 'Parent task is invalid', issue.errors.full_messages
199 end
199 end
200
200
201 def assert_visibility_match(user, issues)
201 def assert_visibility_match(user, issues)
202 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
202 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
203 end
203 end
204
204
205 def test_visible_scope_for_anonymous
205 def test_visible_scope_for_anonymous
206 # Anonymous user should see issues of public projects only
206 # Anonymous user should see issues of public projects only
207 issues = Issue.visible(User.anonymous).all
207 issues = Issue.visible(User.anonymous).all
208 assert issues.any?
208 assert issues.any?
209 assert_nil issues.detect {|issue| !issue.project.is_public?}
209 assert_nil issues.detect {|issue| !issue.project.is_public?}
210 assert_nil issues.detect {|issue| issue.is_private?}
210 assert_nil issues.detect {|issue| issue.is_private?}
211 assert_visibility_match User.anonymous, issues
211 assert_visibility_match User.anonymous, issues
212 end
212 end
213
213
214 def test_visible_scope_for_anonymous_without_view_issues_permissions
214 def test_visible_scope_for_anonymous_without_view_issues_permissions
215 # Anonymous user should not see issues without permission
215 # Anonymous user should not see issues without permission
216 Role.anonymous.remove_permission!(:view_issues)
216 Role.anonymous.remove_permission!(:view_issues)
217 issues = Issue.visible(User.anonymous).all
217 issues = Issue.visible(User.anonymous).all
218 assert issues.empty?
218 assert issues.empty?
219 assert_visibility_match User.anonymous, issues
219 assert_visibility_match User.anonymous, issues
220 end
220 end
221
221
222 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
222 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
223 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
223 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
224 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
224 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
225 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
225 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
226 assert !issue.visible?(User.anonymous)
226 assert !issue.visible?(User.anonymous)
227 end
227 end
228
228
229 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
229 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
230 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
230 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
231 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
231 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
232 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
232 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
233 assert !issue.visible?(User.anonymous)
233 assert !issue.visible?(User.anonymous)
234 end
234 end
235
235
236 def test_visible_scope_for_non_member
236 def test_visible_scope_for_non_member
237 user = User.find(9)
237 user = User.find(9)
238 assert user.projects.empty?
238 assert user.projects.empty?
239 # Non member user should see issues of public projects only
239 # Non member user should see issues of public projects only
240 issues = Issue.visible(user).all
240 issues = Issue.visible(user).all
241 assert issues.any?
241 assert issues.any?
242 assert_nil issues.detect {|issue| !issue.project.is_public?}
242 assert_nil issues.detect {|issue| !issue.project.is_public?}
243 assert_nil issues.detect {|issue| issue.is_private?}
243 assert_nil issues.detect {|issue| issue.is_private?}
244 assert_visibility_match user, issues
244 assert_visibility_match user, issues
245 end
245 end
246
246
247 def test_visible_scope_for_non_member_with_own_issues_visibility
247 def test_visible_scope_for_non_member_with_own_issues_visibility
248 Role.non_member.update_attribute :issues_visibility, 'own'
248 Role.non_member.update_attribute :issues_visibility, 'own'
249 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
249 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
250 user = User.find(9)
250 user = User.find(9)
251
251
252 issues = Issue.visible(user).all
252 issues = Issue.visible(user).all
253 assert issues.any?
253 assert issues.any?
254 assert_nil issues.detect {|issue| issue.author != user}
254 assert_nil issues.detect {|issue| issue.author != user}
255 assert_visibility_match user, issues
255 assert_visibility_match user, issues
256 end
256 end
257
257
258 def test_visible_scope_for_non_member_without_view_issues_permissions
258 def test_visible_scope_for_non_member_without_view_issues_permissions
259 # Non member user should not see issues without permission
259 # Non member user should not see issues without permission
260 Role.non_member.remove_permission!(:view_issues)
260 Role.non_member.remove_permission!(:view_issues)
261 user = User.find(9)
261 user = User.find(9)
262 assert user.projects.empty?
262 assert user.projects.empty?
263 issues = Issue.visible(user).all
263 issues = Issue.visible(user).all
264 assert issues.empty?
264 assert issues.empty?
265 assert_visibility_match user, issues
265 assert_visibility_match user, issues
266 end
266 end
267
267
268 def test_visible_scope_for_member
268 def test_visible_scope_for_member
269 user = User.find(9)
269 user = User.find(9)
270 # User should see issues of projects for which user has view_issues permissions only
270 # User should see issues of projects for which user has view_issues permissions only
271 Role.non_member.remove_permission!(:view_issues)
271 Role.non_member.remove_permission!(:view_issues)
272 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
272 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
273 issues = Issue.visible(user).all
273 issues = Issue.visible(user).all
274 assert issues.any?
274 assert issues.any?
275 assert_nil issues.detect {|issue| issue.project_id != 3}
275 assert_nil issues.detect {|issue| issue.project_id != 3}
276 assert_nil issues.detect {|issue| issue.is_private?}
276 assert_nil issues.detect {|issue| issue.is_private?}
277 assert_visibility_match user, issues
277 assert_visibility_match user, issues
278 end
278 end
279
279
280 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
280 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
281 user = User.find(8)
281 user = User.find(8)
282 assert user.groups.any?
282 assert user.groups.any?
283 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
283 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
284 Role.non_member.remove_permission!(:view_issues)
284 Role.non_member.remove_permission!(:view_issues)
285
285
286 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
286 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
287 :status_id => 1, :priority => IssuePriority.all.first,
287 :status_id => 1, :priority => IssuePriority.all.first,
288 :subject => 'Assignment test',
288 :subject => 'Assignment test',
289 :assigned_to => user.groups.first,
289 :assigned_to => user.groups.first,
290 :is_private => true)
290 :is_private => true)
291
291
292 Role.find(2).update_attribute :issues_visibility, 'default'
292 Role.find(2).update_attribute :issues_visibility, 'default'
293 issues = Issue.visible(User.find(8)).all
293 issues = Issue.visible(User.find(8)).all
294 assert issues.any?
294 assert issues.any?
295 assert issues.include?(issue)
295 assert issues.include?(issue)
296
296
297 Role.find(2).update_attribute :issues_visibility, 'own'
297 Role.find(2).update_attribute :issues_visibility, 'own'
298 issues = Issue.visible(User.find(8)).all
298 issues = Issue.visible(User.find(8)).all
299 assert issues.any?
299 assert issues.any?
300 assert issues.include?(issue)
300 assert issues.include?(issue)
301 end
301 end
302
302
303 def test_visible_scope_for_admin
303 def test_visible_scope_for_admin
304 user = User.find(1)
304 user = User.find(1)
305 user.members.each(&:destroy)
305 user.members.each(&:destroy)
306 assert user.projects.empty?
306 assert user.projects.empty?
307 issues = Issue.visible(user).all
307 issues = Issue.visible(user).all
308 assert issues.any?
308 assert issues.any?
309 # Admin should see issues on private projects that admin does not belong to
309 # Admin should see issues on private projects that admin does not belong to
310 assert issues.detect {|issue| !issue.project.is_public?}
310 assert issues.detect {|issue| !issue.project.is_public?}
311 # Admin should see private issues of other users
311 # Admin should see private issues of other users
312 assert issues.detect {|issue| issue.is_private? && issue.author != user}
312 assert issues.detect {|issue| issue.is_private? && issue.author != user}
313 assert_visibility_match user, issues
313 assert_visibility_match user, issues
314 end
314 end
315
315
316 def test_visible_scope_with_project
316 def test_visible_scope_with_project
317 project = Project.find(1)
317 project = Project.find(1)
318 issues = Issue.visible(User.find(2), :project => project).all
318 issues = Issue.visible(User.find(2), :project => project).all
319 projects = issues.collect(&:project).uniq
319 projects = issues.collect(&:project).uniq
320 assert_equal 1, projects.size
320 assert_equal 1, projects.size
321 assert_equal project, projects.first
321 assert_equal project, projects.first
322 end
322 end
323
323
324 def test_visible_scope_with_project_and_subprojects
324 def test_visible_scope_with_project_and_subprojects
325 project = Project.find(1)
325 project = Project.find(1)
326 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
326 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
327 projects = issues.collect(&:project).uniq
327 projects = issues.collect(&:project).uniq
328 assert projects.size > 1
328 assert projects.size > 1
329 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
329 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
330 end
330 end
331
331
332 def test_visible_and_nested_set_scopes
332 def test_visible_and_nested_set_scopes
333 assert_equal 0, Issue.find(1).descendants.visible.all.size
333 assert_equal 0, Issue.find(1).descendants.visible.all.size
334 end
334 end
335
335
336 def test_open_scope
336 def test_open_scope
337 issues = Issue.open.all
337 issues = Issue.open.all
338 assert_nil issues.detect(&:closed?)
338 assert_nil issues.detect(&:closed?)
339 end
339 end
340
340
341 def test_open_scope_with_arg
341 def test_open_scope_with_arg
342 issues = Issue.open(false).all
342 issues = Issue.open(false).all
343 assert_equal issues, issues.select(&:closed?)
343 assert_equal issues, issues.select(&:closed?)
344 end
344 end
345
345
346 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
346 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
347 version = Version.find(2)
347 version = Version.find(2)
348 assert version.fixed_issues.any?
348 assert version.fixed_issues.any?
349 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
349 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
350 end
350 end
351
351
352 def test_fixed_version_scope_with_empty_array_should_return_no_result
352 def test_fixed_version_scope_with_empty_array_should_return_no_result
353 assert_equal 0, Issue.fixed_version([]).count
353 assert_equal 0, Issue.fixed_version([]).count
354 end
354 end
355
355
356 def test_errors_full_messages_should_include_custom_fields_errors
356 def test_errors_full_messages_should_include_custom_fields_errors
357 field = IssueCustomField.find_by_name('Database')
357 field = IssueCustomField.find_by_name('Database')
358
358
359 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
359 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
360 :status_id => 1, :subject => 'test_create',
360 :status_id => 1, :subject => 'test_create',
361 :description => 'IssueTest#test_create_with_required_custom_field')
361 :description => 'IssueTest#test_create_with_required_custom_field')
362 assert issue.available_custom_fields.include?(field)
362 assert issue.available_custom_fields.include?(field)
363 # Invalid value
363 # Invalid value
364 issue.custom_field_values = { field.id => 'SQLServer' }
364 issue.custom_field_values = { field.id => 'SQLServer' }
365
365
366 assert !issue.valid?
366 assert !issue.valid?
367 assert_equal 1, issue.errors.full_messages.size
367 assert_equal 1, issue.errors.full_messages.size
368 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
368 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
369 issue.errors.full_messages.first
369 issue.errors.full_messages.first
370 end
370 end
371
371
372 def test_update_issue_with_required_custom_field
372 def test_update_issue_with_required_custom_field
373 field = IssueCustomField.find_by_name('Database')
373 field = IssueCustomField.find_by_name('Database')
374 field.update_attribute(:is_required, true)
374 field.update_attribute(:is_required, true)
375
375
376 issue = Issue.find(1)
376 issue = Issue.find(1)
377 assert_nil issue.custom_value_for(field)
377 assert_nil issue.custom_value_for(field)
378 assert issue.available_custom_fields.include?(field)
378 assert issue.available_custom_fields.include?(field)
379 # No change to custom values, issue can be saved
379 # No change to custom values, issue can be saved
380 assert issue.save
380 assert issue.save
381 # Blank value
381 # Blank value
382 issue.custom_field_values = { field.id => '' }
382 issue.custom_field_values = { field.id => '' }
383 assert !issue.save
383 assert !issue.save
384 # Valid value
384 # Valid value
385 issue.custom_field_values = { field.id => 'PostgreSQL' }
385 issue.custom_field_values = { field.id => 'PostgreSQL' }
386 assert issue.save
386 assert issue.save
387 issue.reload
387 issue.reload
388 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
388 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
389 end
389 end
390
390
391 def test_should_not_update_attributes_if_custom_fields_validation_fails
391 def test_should_not_update_attributes_if_custom_fields_validation_fails
392 issue = Issue.find(1)
392 issue = Issue.find(1)
393 field = IssueCustomField.find_by_name('Database')
393 field = IssueCustomField.find_by_name('Database')
394 assert issue.available_custom_fields.include?(field)
394 assert issue.available_custom_fields.include?(field)
395
395
396 issue.custom_field_values = { field.id => 'Invalid' }
396 issue.custom_field_values = { field.id => 'Invalid' }
397 issue.subject = 'Should be not be saved'
397 issue.subject = 'Should be not be saved'
398 assert !issue.save
398 assert !issue.save
399
399
400 issue.reload
400 issue.reload
401 assert_equal "Can't print recipes", issue.subject
401 assert_equal "Can't print recipes", issue.subject
402 end
402 end
403
403
404 def test_should_not_recreate_custom_values_objects_on_update
404 def test_should_not_recreate_custom_values_objects_on_update
405 field = IssueCustomField.find_by_name('Database')
405 field = IssueCustomField.find_by_name('Database')
406
406
407 issue = Issue.find(1)
407 issue = Issue.find(1)
408 issue.custom_field_values = { field.id => 'PostgreSQL' }
408 issue.custom_field_values = { field.id => 'PostgreSQL' }
409 assert issue.save
409 assert issue.save
410 custom_value = issue.custom_value_for(field)
410 custom_value = issue.custom_value_for(field)
411 issue.reload
411 issue.reload
412 issue.custom_field_values = { field.id => 'MySQL' }
412 issue.custom_field_values = { field.id => 'MySQL' }
413 assert issue.save
413 assert issue.save
414 issue.reload
414 issue.reload
415 assert_equal custom_value.id, issue.custom_value_for(field).id
415 assert_equal custom_value.id, issue.custom_value_for(field).id
416 end
416 end
417
417
418 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
418 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
419 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
419 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
420 :status_id => 1, :subject => 'Test',
420 :status_id => 1, :subject => 'Test',
421 :custom_field_values => {'2' => 'Test'})
421 :custom_field_values => {'2' => 'Test'})
422 assert !Tracker.find(2).custom_field_ids.include?(2)
422 assert !Tracker.find(2).custom_field_ids.include?(2)
423
423
424 issue = Issue.find(issue.id)
424 issue = Issue.find(issue.id)
425 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
425 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
426
426
427 issue = Issue.find(issue.id)
427 issue = Issue.find(issue.id)
428 custom_value = issue.custom_value_for(2)
428 custom_value = issue.custom_value_for(2)
429 assert_not_nil custom_value
429 assert_not_nil custom_value
430 assert_equal 'Test', custom_value.value
430 assert_equal 'Test', custom_value.value
431 end
431 end
432
432
433 def test_assigning_tracker_id_should_reload_custom_fields_values
433 def test_assigning_tracker_id_should_reload_custom_fields_values
434 issue = Issue.new(:project => Project.find(1))
434 issue = Issue.new(:project => Project.find(1))
435 assert issue.custom_field_values.empty?
435 assert issue.custom_field_values.empty?
436 issue.tracker_id = 1
436 issue.tracker_id = 1
437 assert issue.custom_field_values.any?
437 assert issue.custom_field_values.any?
438 end
438 end
439
439
440 def test_assigning_attributes_should_assign_project_and_tracker_first
440 def test_assigning_attributes_should_assign_project_and_tracker_first
441 seq = sequence('seq')
441 seq = sequence('seq')
442 issue = Issue.new
442 issue = Issue.new
443 issue.expects(:project_id=).in_sequence(seq)
443 issue.expects(:project_id=).in_sequence(seq)
444 issue.expects(:tracker_id=).in_sequence(seq)
444 issue.expects(:tracker_id=).in_sequence(seq)
445 issue.expects(:subject=).in_sequence(seq)
445 issue.expects(:subject=).in_sequence(seq)
446 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
446 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
447 end
447 end
448
448
449 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
449 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
450 attributes = ActiveSupport::OrderedHash.new
450 attributes = ActiveSupport::OrderedHash.new
451 attributes['custom_field_values'] = { '1' => 'MySQL' }
451 attributes['custom_field_values'] = { '1' => 'MySQL' }
452 attributes['tracker_id'] = '1'
452 attributes['tracker_id'] = '1'
453 issue = Issue.new(:project => Project.find(1))
453 issue = Issue.new(:project => Project.find(1))
454 issue.attributes = attributes
454 issue.attributes = attributes
455 assert_equal 'MySQL', issue.custom_field_value(1)
455 assert_equal 'MySQL', issue.custom_field_value(1)
456 end
456 end
457
457
458 def test_reload_should_reload_custom_field_values
458 def test_reload_should_reload_custom_field_values
459 issue = Issue.generate!
459 issue = Issue.generate!
460 issue.custom_field_values = {'2' => 'Foo'}
460 issue.custom_field_values = {'2' => 'Foo'}
461 issue.save!
461 issue.save!
462
462
463 issue = Issue.order('id desc').first
463 issue = Issue.order('id desc').first
464 assert_equal 'Foo', issue.custom_field_value(2)
464 assert_equal 'Foo', issue.custom_field_value(2)
465
465
466 issue.custom_field_values = {'2' => 'Bar'}
466 issue.custom_field_values = {'2' => 'Bar'}
467 assert_equal 'Bar', issue.custom_field_value(2)
467 assert_equal 'Bar', issue.custom_field_value(2)
468
468
469 issue.reload
469 issue.reload
470 assert_equal 'Foo', issue.custom_field_value(2)
470 assert_equal 'Foo', issue.custom_field_value(2)
471 end
471 end
472
472
473 def test_should_update_issue_with_disabled_tracker
473 def test_should_update_issue_with_disabled_tracker
474 p = Project.find(1)
474 p = Project.find(1)
475 issue = Issue.find(1)
475 issue = Issue.find(1)
476
476
477 p.trackers.delete(issue.tracker)
477 p.trackers.delete(issue.tracker)
478 assert !p.trackers.include?(issue.tracker)
478 assert !p.trackers.include?(issue.tracker)
479
479
480 issue.reload
480 issue.reload
481 issue.subject = 'New subject'
481 issue.subject = 'New subject'
482 assert issue.save
482 assert issue.save
483 end
483 end
484
484
485 def test_should_not_set_a_disabled_tracker
485 def test_should_not_set_a_disabled_tracker
486 p = Project.find(1)
486 p = Project.find(1)
487 p.trackers.delete(Tracker.find(2))
487 p.trackers.delete(Tracker.find(2))
488
488
489 issue = Issue.find(1)
489 issue = Issue.find(1)
490 issue.tracker_id = 2
490 issue.tracker_id = 2
491 issue.subject = 'New subject'
491 issue.subject = 'New subject'
492 assert !issue.save
492 assert !issue.save
493 assert_not_equal [], issue.errors[:tracker_id]
493 assert_not_equal [], issue.errors[:tracker_id]
494 end
494 end
495
495
496 def test_category_based_assignment
496 def test_category_based_assignment
497 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
497 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
498 :status_id => 1, :priority => IssuePriority.all.first,
498 :status_id => 1, :priority => IssuePriority.all.first,
499 :subject => 'Assignment test',
499 :subject => 'Assignment test',
500 :description => 'Assignment test', :category_id => 1)
500 :description => 'Assignment test', :category_id => 1)
501 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
501 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
502 end
502 end
503
503
504 def test_new_statuses_allowed_to
504 def test_new_statuses_allowed_to
505 WorkflowTransition.delete_all
505 WorkflowTransition.delete_all
506 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
506 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
507 :old_status_id => 1, :new_status_id => 2,
507 :old_status_id => 1, :new_status_id => 2,
508 :author => false, :assignee => false)
508 :author => false, :assignee => false)
509 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
509 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
510 :old_status_id => 1, :new_status_id => 3,
510 :old_status_id => 1, :new_status_id => 3,
511 :author => true, :assignee => false)
511 :author => true, :assignee => false)
512 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
512 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
513 :old_status_id => 1, :new_status_id => 4,
513 :old_status_id => 1, :new_status_id => 4,
514 :author => false, :assignee => true)
514 :author => false, :assignee => true)
515 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
515 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
516 :old_status_id => 1, :new_status_id => 5,
516 :old_status_id => 1, :new_status_id => 5,
517 :author => true, :assignee => true)
517 :author => true, :assignee => true)
518 status = IssueStatus.find(1)
518 status = IssueStatus.find(1)
519 role = Role.find(1)
519 role = Role.find(1)
520 tracker = Tracker.find(1)
520 tracker = Tracker.find(1)
521 user = User.find(2)
521 user = User.find(2)
522
522
523 issue = Issue.generate!(:tracker => tracker, :status => status,
523 issue = Issue.generate!(:tracker => tracker, :status => status,
524 :project_id => 1, :author_id => 1)
524 :project_id => 1, :author_id => 1)
525 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
525 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
526
526
527 issue = Issue.generate!(:tracker => tracker, :status => status,
527 issue = Issue.generate!(:tracker => tracker, :status => status,
528 :project_id => 1, :author => user)
528 :project_id => 1, :author => user)
529 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
529 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
530
530
531 issue = Issue.generate!(:tracker => tracker, :status => status,
531 issue = Issue.generate!(:tracker => tracker, :status => status,
532 :project_id => 1, :author_id => 1,
532 :project_id => 1, :author_id => 1,
533 :assigned_to => user)
533 :assigned_to => user)
534 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
534 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
535
535
536 issue = Issue.generate!(:tracker => tracker, :status => status,
536 issue = Issue.generate!(:tracker => tracker, :status => status,
537 :project_id => 1, :author => user,
537 :project_id => 1, :author => user,
538 :assigned_to => user)
538 :assigned_to => user)
539 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
539 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
540
540
541 group = Group.generate!
541 group = Group.generate!
542 group.users << user
542 group.users << user
543 issue = Issue.generate!(:tracker => tracker, :status => status,
543 issue = Issue.generate!(:tracker => tracker, :status => status,
544 :project_id => 1, :author => user,
544 :project_id => 1, :author => user,
545 :assigned_to => group)
545 :assigned_to => group)
546 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
546 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
547 end
547 end
548
548
549 def test_new_statuses_allowed_to_should_consider_group_assignment
549 def test_new_statuses_allowed_to_should_consider_group_assignment
550 WorkflowTransition.delete_all
550 WorkflowTransition.delete_all
551 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
551 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
552 :old_status_id => 1, :new_status_id => 4,
552 :old_status_id => 1, :new_status_id => 4,
553 :author => false, :assignee => true)
553 :author => false, :assignee => true)
554 user = User.find(2)
554 user = User.find(2)
555 group = Group.generate!
555 group = Group.generate!
556 group.users << user
556 group.users << user
557
557
558 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
558 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
559 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
559 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
560 end
560 end
561
561
562 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
562 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
563 admin = User.find(1)
563 admin = User.find(1)
564 issue = Issue.find(1)
564 issue = Issue.find(1)
565 assert !admin.member_of?(issue.project)
565 assert !admin.member_of?(issue.project)
566 expected_statuses = [issue.status] +
566 expected_statuses = [issue.status] +
567 WorkflowTransition.find_all_by_old_status_id(
567 WorkflowTransition.find_all_by_old_status_id(
568 issue.status_id).map(&:new_status).uniq.sort
568 issue.status_id).map(&:new_status).uniq.sort
569 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
569 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
570 end
570 end
571
571
572 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
572 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
573 issue = Issue.find(1).copy
573 issue = Issue.find(1).copy
574 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
574 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
575
575
576 issue = Issue.find(2).copy
576 issue = Issue.find(2).copy
577 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
577 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
578 end
578 end
579
579
580 def test_safe_attributes_names_should_not_include_disabled_field
580 def test_safe_attributes_names_should_not_include_disabled_field
581 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
581 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
582
582
583 issue = Issue.new(:tracker => tracker)
583 issue = Issue.new(:tracker => tracker)
584 assert_include 'tracker_id', issue.safe_attribute_names
584 assert_include 'tracker_id', issue.safe_attribute_names
585 assert_include 'status_id', issue.safe_attribute_names
585 assert_include 'status_id', issue.safe_attribute_names
586 assert_include 'subject', issue.safe_attribute_names
586 assert_include 'subject', issue.safe_attribute_names
587 assert_include 'description', issue.safe_attribute_names
587 assert_include 'description', issue.safe_attribute_names
588 assert_include 'custom_field_values', issue.safe_attribute_names
588 assert_include 'custom_field_values', issue.safe_attribute_names
589 assert_include 'custom_fields', issue.safe_attribute_names
589 assert_include 'custom_fields', issue.safe_attribute_names
590 assert_include 'lock_version', issue.safe_attribute_names
590 assert_include 'lock_version', issue.safe_attribute_names
591
591
592 tracker.core_fields.each do |field|
592 tracker.core_fields.each do |field|
593 assert_include field, issue.safe_attribute_names
593 assert_include field, issue.safe_attribute_names
594 end
594 end
595
595
596 tracker.disabled_core_fields.each do |field|
596 tracker.disabled_core_fields.each do |field|
597 assert_not_include field, issue.safe_attribute_names
597 assert_not_include field, issue.safe_attribute_names
598 end
598 end
599 end
599 end
600
600
601 def test_safe_attributes_should_ignore_disabled_fields
601 def test_safe_attributes_should_ignore_disabled_fields
602 tracker = Tracker.find(1)
602 tracker = Tracker.find(1)
603 tracker.core_fields = %w(assigned_to_id due_date)
603 tracker.core_fields = %w(assigned_to_id due_date)
604 tracker.save!
604 tracker.save!
605
605
606 issue = Issue.new(:tracker => tracker)
606 issue = Issue.new(:tracker => tracker)
607 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
607 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
608 assert_nil issue.start_date
608 assert_nil issue.start_date
609 assert_equal Date.parse('2012-07-14'), issue.due_date
609 assert_equal Date.parse('2012-07-14'), issue.due_date
610 end
610 end
611
611
612 def test_safe_attributes_should_accept_target_tracker_enabled_fields
612 def test_safe_attributes_should_accept_target_tracker_enabled_fields
613 source = Tracker.find(1)
613 source = Tracker.find(1)
614 source.core_fields = []
614 source.core_fields = []
615 source.save!
615 source.save!
616 target = Tracker.find(2)
616 target = Tracker.find(2)
617 target.core_fields = %w(assigned_to_id due_date)
617 target.core_fields = %w(assigned_to_id due_date)
618 target.save!
618 target.save!
619
619
620 issue = Issue.new(:tracker => source)
620 issue = Issue.new(:tracker => source)
621 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
621 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
622 assert_equal target, issue.tracker
622 assert_equal target, issue.tracker
623 assert_equal Date.parse('2012-07-14'), issue.due_date
623 assert_equal Date.parse('2012-07-14'), issue.due_date
624 end
624 end
625
625
626 def test_safe_attributes_should_not_include_readonly_fields
626 def test_safe_attributes_should_not_include_readonly_fields
627 WorkflowPermission.delete_all
627 WorkflowPermission.delete_all
628 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
628 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
629 :role_id => 1, :field_name => 'due_date',
629 :role_id => 1, :field_name => 'due_date',
630 :rule => 'readonly')
630 :rule => 'readonly')
631 user = User.find(2)
631 user = User.find(2)
632
632
633 issue = Issue.new(:project_id => 1, :tracker_id => 1)
633 issue = Issue.new(:project_id => 1, :tracker_id => 1)
634 assert_equal %w(due_date), issue.read_only_attribute_names(user)
634 assert_equal %w(due_date), issue.read_only_attribute_names(user)
635 assert_not_include 'due_date', issue.safe_attribute_names(user)
635 assert_not_include 'due_date', issue.safe_attribute_names(user)
636
636
637 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
637 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
638 assert_equal Date.parse('2012-07-14'), issue.start_date
638 assert_equal Date.parse('2012-07-14'), issue.start_date
639 assert_nil issue.due_date
639 assert_nil issue.due_date
640 end
640 end
641
641
642 def test_safe_attributes_should_not_include_readonly_custom_fields
642 def test_safe_attributes_should_not_include_readonly_custom_fields
643 cf1 = IssueCustomField.create!(:name => 'Writable field',
643 cf1 = IssueCustomField.create!(:name => 'Writable field',
644 :field_format => 'string',
644 :field_format => 'string',
645 :is_for_all => true, :tracker_ids => [1])
645 :is_for_all => true, :tracker_ids => [1])
646 cf2 = IssueCustomField.create!(:name => 'Readonly field',
646 cf2 = IssueCustomField.create!(:name => 'Readonly field',
647 :field_format => 'string',
647 :field_format => 'string',
648 :is_for_all => true, :tracker_ids => [1])
648 :is_for_all => true, :tracker_ids => [1])
649 WorkflowPermission.delete_all
649 WorkflowPermission.delete_all
650 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
650 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
651 :role_id => 1, :field_name => cf2.id.to_s,
651 :role_id => 1, :field_name => cf2.id.to_s,
652 :rule => 'readonly')
652 :rule => 'readonly')
653 user = User.find(2)
653 user = User.find(2)
654 issue = Issue.new(:project_id => 1, :tracker_id => 1)
654 issue = Issue.new(:project_id => 1, :tracker_id => 1)
655 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
655 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
656 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
656 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
657
657
658 issue.send :safe_attributes=, {'custom_field_values' => {
658 issue.send :safe_attributes=, {'custom_field_values' => {
659 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
659 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
660 }}, user
660 }}, user
661 assert_equal 'value1', issue.custom_field_value(cf1)
661 assert_equal 'value1', issue.custom_field_value(cf1)
662 assert_nil issue.custom_field_value(cf2)
662 assert_nil issue.custom_field_value(cf2)
663
663
664 issue.send :safe_attributes=, {'custom_fields' => [
664 issue.send :safe_attributes=, {'custom_fields' => [
665 {'id' => cf1.id.to_s, 'value' => 'valuea'},
665 {'id' => cf1.id.to_s, 'value' => 'valuea'},
666 {'id' => cf2.id.to_s, 'value' => 'valueb'}
666 {'id' => cf2.id.to_s, 'value' => 'valueb'}
667 ]}, user
667 ]}, user
668 assert_equal 'valuea', issue.custom_field_value(cf1)
668 assert_equal 'valuea', issue.custom_field_value(cf1)
669 assert_nil issue.custom_field_value(cf2)
669 assert_nil issue.custom_field_value(cf2)
670 end
670 end
671
671
672 def test_editable_custom_field_values_should_return_non_readonly_custom_values
672 def test_editable_custom_field_values_should_return_non_readonly_custom_values
673 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
673 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
674 :is_for_all => true, :tracker_ids => [1, 2])
674 :is_for_all => true, :tracker_ids => [1, 2])
675 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
675 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
676 :is_for_all => true, :tracker_ids => [1, 2])
676 :is_for_all => true, :tracker_ids => [1, 2])
677 WorkflowPermission.delete_all
677 WorkflowPermission.delete_all
678 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
678 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
679 :field_name => cf2.id.to_s, :rule => 'readonly')
679 :field_name => cf2.id.to_s, :rule => 'readonly')
680 user = User.find(2)
680 user = User.find(2)
681
681
682 issue = Issue.new(:project_id => 1, :tracker_id => 1)
682 issue = Issue.new(:project_id => 1, :tracker_id => 1)
683 values = issue.editable_custom_field_values(user)
683 values = issue.editable_custom_field_values(user)
684 assert values.detect {|value| value.custom_field == cf1}
684 assert values.detect {|value| value.custom_field == cf1}
685 assert_nil values.detect {|value| value.custom_field == cf2}
685 assert_nil values.detect {|value| value.custom_field == cf2}
686
686
687 issue.tracker_id = 2
687 issue.tracker_id = 2
688 values = issue.editable_custom_field_values(user)
688 values = issue.editable_custom_field_values(user)
689 assert values.detect {|value| value.custom_field == cf1}
689 assert values.detect {|value| value.custom_field == cf1}
690 assert values.detect {|value| value.custom_field == cf2}
690 assert values.detect {|value| value.custom_field == cf2}
691 end
691 end
692
692
693 def test_safe_attributes_should_accept_target_tracker_writable_fields
693 def test_safe_attributes_should_accept_target_tracker_writable_fields
694 WorkflowPermission.delete_all
694 WorkflowPermission.delete_all
695 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
695 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
696 :role_id => 1, :field_name => 'due_date',
696 :role_id => 1, :field_name => 'due_date',
697 :rule => 'readonly')
697 :rule => 'readonly')
698 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
698 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
699 :role_id => 1, :field_name => 'start_date',
699 :role_id => 1, :field_name => 'start_date',
700 :rule => 'readonly')
700 :rule => 'readonly')
701 user = User.find(2)
701 user = User.find(2)
702
702
703 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
703 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
704
704
705 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
705 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
706 'due_date' => '2012-07-14'}, user
706 'due_date' => '2012-07-14'}, user
707 assert_equal Date.parse('2012-07-12'), issue.start_date
707 assert_equal Date.parse('2012-07-12'), issue.start_date
708 assert_nil issue.due_date
708 assert_nil issue.due_date
709
709
710 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
710 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
711 'due_date' => '2012-07-16',
711 'due_date' => '2012-07-16',
712 'tracker_id' => 2}, user
712 'tracker_id' => 2}, user
713 assert_equal Date.parse('2012-07-12'), issue.start_date
713 assert_equal Date.parse('2012-07-12'), issue.start_date
714 assert_equal Date.parse('2012-07-16'), issue.due_date
714 assert_equal Date.parse('2012-07-16'), issue.due_date
715 end
715 end
716
716
717 def test_safe_attributes_should_accept_target_status_writable_fields
717 def test_safe_attributes_should_accept_target_status_writable_fields
718 WorkflowPermission.delete_all
718 WorkflowPermission.delete_all
719 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
719 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
720 :role_id => 1, :field_name => 'due_date',
720 :role_id => 1, :field_name => 'due_date',
721 :rule => 'readonly')
721 :rule => 'readonly')
722 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
722 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
723 :role_id => 1, :field_name => 'start_date',
723 :role_id => 1, :field_name => 'start_date',
724 :rule => 'readonly')
724 :rule => 'readonly')
725 user = User.find(2)
725 user = User.find(2)
726
726
727 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
727 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
728
728
729 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
729 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
730 'due_date' => '2012-07-14'},
730 'due_date' => '2012-07-14'},
731 user
731 user
732 assert_equal Date.parse('2012-07-12'), issue.start_date
732 assert_equal Date.parse('2012-07-12'), issue.start_date
733 assert_nil issue.due_date
733 assert_nil issue.due_date
734
734
735 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
735 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
736 'due_date' => '2012-07-16',
736 'due_date' => '2012-07-16',
737 'status_id' => 2},
737 'status_id' => 2},
738 user
738 user
739 assert_equal Date.parse('2012-07-12'), issue.start_date
739 assert_equal Date.parse('2012-07-12'), issue.start_date
740 assert_equal Date.parse('2012-07-16'), issue.due_date
740 assert_equal Date.parse('2012-07-16'), issue.due_date
741 end
741 end
742
742
743 def test_required_attributes_should_be_validated
743 def test_required_attributes_should_be_validated
744 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
744 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
745 :is_for_all => true, :tracker_ids => [1, 2])
745 :is_for_all => true, :tracker_ids => [1, 2])
746
746
747 WorkflowPermission.delete_all
747 WorkflowPermission.delete_all
748 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
748 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
749 :role_id => 1, :field_name => 'due_date',
749 :role_id => 1, :field_name => 'due_date',
750 :rule => 'required')
750 :rule => 'required')
751 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
751 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
752 :role_id => 1, :field_name => 'category_id',
752 :role_id => 1, :field_name => 'category_id',
753 :rule => 'required')
753 :rule => 'required')
754 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
754 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
755 :role_id => 1, :field_name => cf.id.to_s,
755 :role_id => 1, :field_name => cf.id.to_s,
756 :rule => 'required')
756 :rule => 'required')
757
757
758 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
758 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
759 :role_id => 1, :field_name => 'start_date',
759 :role_id => 1, :field_name => 'start_date',
760 :rule => 'required')
760 :rule => 'required')
761 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
761 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
762 :role_id => 1, :field_name => cf.id.to_s,
762 :role_id => 1, :field_name => cf.id.to_s,
763 :rule => 'required')
763 :rule => 'required')
764 user = User.find(2)
764 user = User.find(2)
765
765
766 issue = Issue.new(:project_id => 1, :tracker_id => 1,
766 issue = Issue.new(:project_id => 1, :tracker_id => 1,
767 :status_id => 1, :subject => 'Required fields',
767 :status_id => 1, :subject => 'Required fields',
768 :author => user)
768 :author => user)
769 assert_equal [cf.id.to_s, "category_id", "due_date"],
769 assert_equal [cf.id.to_s, "category_id", "due_date"],
770 issue.required_attribute_names(user).sort
770 issue.required_attribute_names(user).sort
771 assert !issue.save, "Issue was saved"
771 assert !issue.save, "Issue was saved"
772 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
772 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
773 issue.errors.full_messages.sort
773 issue.errors.full_messages.sort
774
774
775 issue.tracker_id = 2
775 issue.tracker_id = 2
776 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
776 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
777 assert !issue.save, "Issue was saved"
777 assert !issue.save, "Issue was saved"
778 assert_equal ["Foo can't be blank", "Start date can't be blank"],
778 assert_equal ["Foo can't be blank", "Start date can't be blank"],
779 issue.errors.full_messages.sort
779 issue.errors.full_messages.sort
780
780
781 issue.start_date = Date.today
781 issue.start_date = Date.today
782 issue.custom_field_values = {cf.id.to_s => 'bar'}
782 issue.custom_field_values = {cf.id.to_s => 'bar'}
783 assert issue.save
783 assert issue.save
784 end
784 end
785
785
786 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
786 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
787 WorkflowPermission.delete_all
787 WorkflowPermission.delete_all
788 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
788 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
789 :role_id => 1, :field_name => 'due_date',
789 :role_id => 1, :field_name => 'due_date',
790 :rule => 'required')
790 :rule => 'required')
791 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
791 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
792 :role_id => 1, :field_name => 'start_date',
792 :role_id => 1, :field_name => 'start_date',
793 :rule => 'required')
793 :rule => 'required')
794 user = User.find(2)
794 user = User.find(2)
795 member = Member.find(1)
795 member = Member.find(1)
796 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
796 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
797
797
798 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
798 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
799
799
800 member.role_ids = [1, 2]
800 member.role_ids = [1, 2]
801 member.save!
801 member.save!
802 assert_equal [], issue.required_attribute_names(user.reload)
802 assert_equal [], issue.required_attribute_names(user.reload)
803
803
804 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
804 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
805 :role_id => 2, :field_name => 'due_date',
805 :role_id => 2, :field_name => 'due_date',
806 :rule => 'required')
806 :rule => 'required')
807 assert_equal %w(due_date), issue.required_attribute_names(user)
807 assert_equal %w(due_date), issue.required_attribute_names(user)
808
808
809 member.role_ids = [1, 2, 3]
809 member.role_ids = [1, 2, 3]
810 member.save!
810 member.save!
811 assert_equal [], issue.required_attribute_names(user.reload)
811 assert_equal [], issue.required_attribute_names(user.reload)
812
812
813 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
813 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
814 :role_id => 2, :field_name => 'due_date',
814 :role_id => 2, :field_name => 'due_date',
815 :rule => 'readonly')
815 :rule => 'readonly')
816 # required + readonly => required
816 # required + readonly => required
817 assert_equal %w(due_date), issue.required_attribute_names(user)
817 assert_equal %w(due_date), issue.required_attribute_names(user)
818 end
818 end
819
819
820 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
820 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
821 WorkflowPermission.delete_all
821 WorkflowPermission.delete_all
822 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
822 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
823 :role_id => 1, :field_name => 'due_date',
823 :role_id => 1, :field_name => 'due_date',
824 :rule => 'readonly')
824 :rule => 'readonly')
825 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
825 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
826 :role_id => 1, :field_name => 'start_date',
826 :role_id => 1, :field_name => 'start_date',
827 :rule => 'readonly')
827 :rule => 'readonly')
828 user = User.find(2)
828 user = User.find(2)
829 member = Member.find(1)
829 member = Member.find(1)
830 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
830 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
831
831
832 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
832 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
833
833
834 member.role_ids = [1, 2]
834 member.role_ids = [1, 2]
835 member.save!
835 member.save!
836 assert_equal [], issue.read_only_attribute_names(user.reload)
836 assert_equal [], issue.read_only_attribute_names(user.reload)
837
837
838 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
838 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
839 :role_id => 2, :field_name => 'due_date',
839 :role_id => 2, :field_name => 'due_date',
840 :rule => 'readonly')
840 :rule => 'readonly')
841 assert_equal %w(due_date), issue.read_only_attribute_names(user)
841 assert_equal %w(due_date), issue.read_only_attribute_names(user)
842 end
842 end
843
843
844 def test_copy
844 def test_copy
845 issue = Issue.new.copy_from(1)
845 issue = Issue.new.copy_from(1)
846 assert issue.copy?
846 assert issue.copy?
847 assert issue.save
847 assert issue.save
848 issue.reload
848 issue.reload
849 orig = Issue.find(1)
849 orig = Issue.find(1)
850 assert_equal orig.subject, issue.subject
850 assert_equal orig.subject, issue.subject
851 assert_equal orig.tracker, issue.tracker
851 assert_equal orig.tracker, issue.tracker
852 assert_equal "125", issue.custom_value_for(2).value
852 assert_equal "125", issue.custom_value_for(2).value
853 end
853 end
854
854
855 def test_copy_should_copy_status
855 def test_copy_should_copy_status
856 orig = Issue.find(8)
856 orig = Issue.find(8)
857 assert orig.status != IssueStatus.default
857 assert orig.status != IssueStatus.default
858
858
859 issue = Issue.new.copy_from(orig)
859 issue = Issue.new.copy_from(orig)
860 assert issue.save
860 assert issue.save
861 issue.reload
861 issue.reload
862 assert_equal orig.status, issue.status
862 assert_equal orig.status, issue.status
863 end
863 end
864
864
865 def test_copy_should_add_relation_with_copied_issue
865 def test_copy_should_add_relation_with_copied_issue
866 copied = Issue.find(1)
866 copied = Issue.find(1)
867 issue = Issue.new.copy_from(copied)
867 issue = Issue.new.copy_from(copied)
868 assert issue.save
868 assert issue.save
869 issue.reload
869 issue.reload
870
870
871 assert_equal 1, issue.relations.size
871 assert_equal 1, issue.relations.size
872 relation = issue.relations.first
872 relation = issue.relations.first
873 assert_equal 'copied_to', relation.relation_type
873 assert_equal 'copied_to', relation.relation_type
874 assert_equal copied, relation.issue_from
874 assert_equal copied, relation.issue_from
875 assert_equal issue, relation.issue_to
875 assert_equal issue, relation.issue_to
876 end
876 end
877
877
878 def test_copy_should_copy_subtasks
878 def test_copy_should_copy_subtasks
879 issue = Issue.generate_with_descendants!
879 issue = Issue.generate_with_descendants!
880
880
881 copy = issue.reload.copy
881 copy = issue.reload.copy
882 copy.author = User.find(7)
882 copy.author = User.find(7)
883 assert_difference 'Issue.count', 1+issue.descendants.count do
883 assert_difference 'Issue.count', 1+issue.descendants.count do
884 assert copy.save
884 assert copy.save
885 end
885 end
886 copy.reload
886 copy.reload
887 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
887 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
888 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
888 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
889 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
889 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
890 assert_equal copy.author, child_copy.author
890 assert_equal copy.author, child_copy.author
891 end
891 end
892
892
893 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
893 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
894 parent = Issue.generate!
894 parent = Issue.generate!
895 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
895 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
896 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
896 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
897
897
898 copy = parent.reload.copy
898 copy = parent.reload.copy
899 copy.parent_issue_id = parent.id
899 copy.parent_issue_id = parent.id
900 copy.author = User.find(7)
900 copy.author = User.find(7)
901 assert_difference 'Issue.count', 3 do
901 assert_difference 'Issue.count', 3 do
902 assert copy.save
902 assert copy.save
903 end
903 end
904 parent.reload
904 parent.reload
905 copy.reload
905 copy.reload
906 assert_equal parent, copy.parent
906 assert_equal parent, copy.parent
907 assert_equal 3, parent.children.count
907 assert_equal 3, parent.children.count
908 assert_equal 5, parent.descendants.count
908 assert_equal 5, parent.descendants.count
909 assert_equal 2, copy.children.count
909 assert_equal 2, copy.children.count
910 assert_equal 2, copy.descendants.count
910 assert_equal 2, copy.descendants.count
911 end
911 end
912
912
913 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
913 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
914 parent = Issue.generate!
914 parent = Issue.generate!
915 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
915 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
916 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
916 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
917
917
918 copy = parent.reload.copy
918 copy = parent.reload.copy
919 copy.parent_issue_id = child1.id
919 copy.parent_issue_id = child1.id
920 copy.author = User.find(7)
920 copy.author = User.find(7)
921 assert_difference 'Issue.count', 3 do
921 assert_difference 'Issue.count', 3 do
922 assert copy.save
922 assert copy.save
923 end
923 end
924 parent.reload
924 parent.reload
925 child1.reload
925 child1.reload
926 copy.reload
926 copy.reload
927 assert_equal child1, copy.parent
927 assert_equal child1, copy.parent
928 assert_equal 2, parent.children.count
928 assert_equal 2, parent.children.count
929 assert_equal 5, parent.descendants.count
929 assert_equal 5, parent.descendants.count
930 assert_equal 1, child1.children.count
930 assert_equal 1, child1.children.count
931 assert_equal 3, child1.descendants.count
931 assert_equal 3, child1.descendants.count
932 assert_equal 2, copy.children.count
932 assert_equal 2, copy.children.count
933 assert_equal 2, copy.descendants.count
933 assert_equal 2, copy.descendants.count
934 end
934 end
935
935
936 def test_copy_should_copy_subtasks_to_target_project
936 def test_copy_should_copy_subtasks_to_target_project
937 issue = Issue.generate_with_descendants!
937 issue = Issue.generate_with_descendants!
938
938
939 copy = issue.copy(:project_id => 3)
939 copy = issue.copy(:project_id => 3)
940 assert_difference 'Issue.count', 1+issue.descendants.count do
940 assert_difference 'Issue.count', 1+issue.descendants.count do
941 assert copy.save
941 assert copy.save
942 end
942 end
943 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
943 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
944 end
944 end
945
945
946 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
946 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
947 issue = Issue.generate_with_descendants!
947 issue = Issue.generate_with_descendants!
948
948
949 copy = issue.reload.copy
949 copy = issue.reload.copy
950 assert_difference 'Issue.count', 1+issue.descendants.count do
950 assert_difference 'Issue.count', 1+issue.descendants.count do
951 assert copy.save
951 assert copy.save
952 assert copy.save
952 assert copy.save
953 end
953 end
954 end
954 end
955
955
956 def test_should_not_call_after_project_change_on_creation
956 def test_should_not_call_after_project_change_on_creation
957 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
957 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
958 :subject => 'Test', :author_id => 1)
958 :subject => 'Test', :author_id => 1)
959 issue.expects(:after_project_change).never
959 issue.expects(:after_project_change).never
960 issue.save!
960 issue.save!
961 end
961 end
962
962
963 def test_should_not_call_after_project_change_on_update
963 def test_should_not_call_after_project_change_on_update
964 issue = Issue.find(1)
964 issue = Issue.find(1)
965 issue.project = Project.find(1)
965 issue.project = Project.find(1)
966 issue.subject = 'No project change'
966 issue.subject = 'No project change'
967 issue.expects(:after_project_change).never
967 issue.expects(:after_project_change).never
968 issue.save!
968 issue.save!
969 end
969 end
970
970
971 def test_should_call_after_project_change_on_project_change
971 def test_should_call_after_project_change_on_project_change
972 issue = Issue.find(1)
972 issue = Issue.find(1)
973 issue.project = Project.find(2)
973 issue.project = Project.find(2)
974 issue.expects(:after_project_change).once
974 issue.expects(:after_project_change).once
975 issue.save!
975 issue.save!
976 end
976 end
977
977
978 def test_adding_journal_should_update_timestamp
978 def test_adding_journal_should_update_timestamp
979 issue = Issue.find(1)
979 issue = Issue.find(1)
980 updated_on_was = issue.updated_on
980 updated_on_was = issue.updated_on
981
981
982 issue.init_journal(User.first, "Adding notes")
982 issue.init_journal(User.first, "Adding notes")
983 assert_difference 'Journal.count' do
983 assert_difference 'Journal.count' do
984 assert issue.save
984 assert issue.save
985 end
985 end
986 issue.reload
986 issue.reload
987
987
988 assert_not_equal updated_on_was, issue.updated_on
988 assert_not_equal updated_on_was, issue.updated_on
989 end
989 end
990
990
991 def test_should_close_duplicates
991 def test_should_close_duplicates
992 # Create 3 issues
992 # Create 3 issues
993 issue1 = Issue.generate!
993 issue1 = Issue.generate!
994 issue2 = Issue.generate!
994 issue2 = Issue.generate!
995 issue3 = Issue.generate!
995 issue3 = Issue.generate!
996
996
997 # 2 is a dupe of 1
997 # 2 is a dupe of 1
998 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
998 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
999 :relation_type => IssueRelation::TYPE_DUPLICATES)
999 :relation_type => IssueRelation::TYPE_DUPLICATES)
1000 # And 3 is a dupe of 2
1000 # And 3 is a dupe of 2
1001 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1001 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1002 :relation_type => IssueRelation::TYPE_DUPLICATES)
1002 :relation_type => IssueRelation::TYPE_DUPLICATES)
1003 # And 3 is a dupe of 1 (circular duplicates)
1003 # And 3 is a dupe of 1 (circular duplicates)
1004 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
1004 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
1005 :relation_type => IssueRelation::TYPE_DUPLICATES)
1005 :relation_type => IssueRelation::TYPE_DUPLICATES)
1006
1006
1007 assert issue1.reload.duplicates.include?(issue2)
1007 assert issue1.reload.duplicates.include?(issue2)
1008
1008
1009 # Closing issue 1
1009 # Closing issue 1
1010 issue1.init_journal(User.first, "Closing issue1")
1010 issue1.init_journal(User.first, "Closing issue1")
1011 issue1.status = IssueStatus.where(:is_closed => true).first
1011 issue1.status = IssueStatus.where(:is_closed => true).first
1012 assert issue1.save
1012 assert issue1.save
1013 # 2 and 3 should be also closed
1013 # 2 and 3 should be also closed
1014 assert issue2.reload.closed?
1014 assert issue2.reload.closed?
1015 assert issue3.reload.closed?
1015 assert issue3.reload.closed?
1016 end
1016 end
1017
1017
1018 def test_should_not_close_duplicated_issue
1018 def test_should_not_close_duplicated_issue
1019 issue1 = Issue.generate!
1019 issue1 = Issue.generate!
1020 issue2 = Issue.generate!
1020 issue2 = Issue.generate!
1021
1021
1022 # 2 is a dupe of 1
1022 # 2 is a dupe of 1
1023 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1023 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1024 :relation_type => IssueRelation::TYPE_DUPLICATES)
1024 :relation_type => IssueRelation::TYPE_DUPLICATES)
1025 # 2 is a dup of 1 but 1 is not a duplicate of 2
1025 # 2 is a dup of 1 but 1 is not a duplicate of 2
1026 assert !issue2.reload.duplicates.include?(issue1)
1026 assert !issue2.reload.duplicates.include?(issue1)
1027
1027
1028 # Closing issue 2
1028 # Closing issue 2
1029 issue2.init_journal(User.first, "Closing issue2")
1029 issue2.init_journal(User.first, "Closing issue2")
1030 issue2.status = IssueStatus.where(:is_closed => true).first
1030 issue2.status = IssueStatus.where(:is_closed => true).first
1031 assert issue2.save
1031 assert issue2.save
1032 # 1 should not be also closed
1032 # 1 should not be also closed
1033 assert !issue1.reload.closed?
1033 assert !issue1.reload.closed?
1034 end
1034 end
1035
1035
1036 def test_assignable_versions
1036 def test_assignable_versions
1037 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1037 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1038 :status_id => 1, :fixed_version_id => 1,
1038 :status_id => 1, :fixed_version_id => 1,
1039 :subject => 'New issue')
1039 :subject => 'New issue')
1040 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1040 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1041 end
1041 end
1042
1042
1043 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1043 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1044 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1044 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1045 :status_id => 1, :fixed_version_id => 1,
1045 :status_id => 1, :fixed_version_id => 1,
1046 :subject => 'New issue')
1046 :subject => 'New issue')
1047 assert !issue.save
1047 assert !issue.save
1048 assert_not_equal [], issue.errors[:fixed_version_id]
1048 assert_not_equal [], issue.errors[:fixed_version_id]
1049 end
1049 end
1050
1050
1051 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1051 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1052 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1052 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1053 :status_id => 1, :fixed_version_id => 2,
1053 :status_id => 1, :fixed_version_id => 2,
1054 :subject => 'New issue')
1054 :subject => 'New issue')
1055 assert !issue.save
1055 assert !issue.save
1056 assert_not_equal [], issue.errors[:fixed_version_id]
1056 assert_not_equal [], issue.errors[:fixed_version_id]
1057 end
1057 end
1058
1058
1059 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1059 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1060 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1060 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1061 :status_id => 1, :fixed_version_id => 3,
1061 :status_id => 1, :fixed_version_id => 3,
1062 :subject => 'New issue')
1062 :subject => 'New issue')
1063 assert issue.save
1063 assert issue.save
1064 end
1064 end
1065
1065
1066 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1066 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1067 issue = Issue.find(11)
1067 issue = Issue.find(11)
1068 assert_equal 'closed', issue.fixed_version.status
1068 assert_equal 'closed', issue.fixed_version.status
1069 issue.subject = 'Subject changed'
1069 issue.subject = 'Subject changed'
1070 assert issue.save
1070 assert issue.save
1071 end
1071 end
1072
1072
1073 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1073 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1074 issue = Issue.find(11)
1074 issue = Issue.find(11)
1075 issue.status_id = 1
1075 issue.status_id = 1
1076 assert !issue.save
1076 assert !issue.save
1077 assert_not_equal [], issue.errors[:base]
1077 assert_not_equal [], issue.errors[:base]
1078 end
1078 end
1079
1079
1080 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1080 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1081 issue = Issue.find(11)
1081 issue = Issue.find(11)
1082 issue.status_id = 1
1082 issue.status_id = 1
1083 issue.fixed_version_id = 3
1083 issue.fixed_version_id = 3
1084 assert issue.save
1084 assert issue.save
1085 end
1085 end
1086
1086
1087 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1087 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1088 issue = Issue.find(12)
1088 issue = Issue.find(12)
1089 assert_equal 'locked', issue.fixed_version.status
1089 assert_equal 'locked', issue.fixed_version.status
1090 issue.status_id = 1
1090 issue.status_id = 1
1091 assert issue.save
1091 assert issue.save
1092 end
1092 end
1093
1093
1094 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1094 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1095 issue = Issue.find(2)
1095 issue = Issue.find(2)
1096 assert_equal 2, issue.fixed_version_id
1096 assert_equal 2, issue.fixed_version_id
1097 issue.project_id = 3
1097 issue.project_id = 3
1098 assert_nil issue.fixed_version_id
1098 assert_nil issue.fixed_version_id
1099 issue.fixed_version_id = 2
1099 issue.fixed_version_id = 2
1100 assert !issue.save
1100 assert !issue.save
1101 assert_include 'Target version is not included in the list', issue.errors.full_messages
1101 assert_include 'Target version is not included in the list', issue.errors.full_messages
1102 end
1102 end
1103
1103
1104 def test_should_keep_shared_version_when_changing_project
1104 def test_should_keep_shared_version_when_changing_project
1105 Version.find(2).update_attribute :sharing, 'tree'
1105 Version.find(2).update_attribute :sharing, 'tree'
1106
1106
1107 issue = Issue.find(2)
1107 issue = Issue.find(2)
1108 assert_equal 2, issue.fixed_version_id
1108 assert_equal 2, issue.fixed_version_id
1109 issue.project_id = 3
1109 issue.project_id = 3
1110 assert_equal 2, issue.fixed_version_id
1110 assert_equal 2, issue.fixed_version_id
1111 assert issue.save
1111 assert issue.save
1112 end
1112 end
1113
1113
1114 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
1114 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
1115 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1115 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1116 end
1116 end
1117
1117
1118 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
1118 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
1119 Project.find(2).disable_module! :issue_tracking
1119 Project.find(2).disable_module! :issue_tracking
1120 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1120 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1121 end
1121 end
1122
1122
1123 def test_move_to_another_project_with_same_category
1123 def test_move_to_another_project_with_same_category
1124 issue = Issue.find(1)
1124 issue = Issue.find(1)
1125 issue.project = Project.find(2)
1125 issue.project = Project.find(2)
1126 assert issue.save
1126 assert issue.save
1127 issue.reload
1127 issue.reload
1128 assert_equal 2, issue.project_id
1128 assert_equal 2, issue.project_id
1129 # Category changes
1129 # Category changes
1130 assert_equal 4, issue.category_id
1130 assert_equal 4, issue.category_id
1131 # Make sure time entries were move to the target project
1131 # Make sure time entries were move to the target project
1132 assert_equal 2, issue.time_entries.first.project_id
1132 assert_equal 2, issue.time_entries.first.project_id
1133 end
1133 end
1134
1134
1135 def test_move_to_another_project_without_same_category
1135 def test_move_to_another_project_without_same_category
1136 issue = Issue.find(2)
1136 issue = Issue.find(2)
1137 issue.project = Project.find(2)
1137 issue.project = Project.find(2)
1138 assert issue.save
1138 assert issue.save
1139 issue.reload
1139 issue.reload
1140 assert_equal 2, issue.project_id
1140 assert_equal 2, issue.project_id
1141 # Category cleared
1141 # Category cleared
1142 assert_nil issue.category_id
1142 assert_nil issue.category_id
1143 end
1143 end
1144
1144
1145 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1145 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1146 issue = Issue.find(1)
1146 issue = Issue.find(1)
1147 issue.update_attribute(:fixed_version_id, 1)
1147 issue.update_attribute(:fixed_version_id, 1)
1148 issue.project = Project.find(2)
1148 issue.project = Project.find(2)
1149 assert issue.save
1149 assert issue.save
1150 issue.reload
1150 issue.reload
1151 assert_equal 2, issue.project_id
1151 assert_equal 2, issue.project_id
1152 # Cleared fixed_version
1152 # Cleared fixed_version
1153 assert_equal nil, issue.fixed_version
1153 assert_equal nil, issue.fixed_version
1154 end
1154 end
1155
1155
1156 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1156 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1157 issue = Issue.find(1)
1157 issue = Issue.find(1)
1158 issue.update_attribute(:fixed_version_id, 4)
1158 issue.update_attribute(:fixed_version_id, 4)
1159 issue.project = Project.find(5)
1159 issue.project = Project.find(5)
1160 assert issue.save
1160 assert issue.save
1161 issue.reload
1161 issue.reload
1162 assert_equal 5, issue.project_id
1162 assert_equal 5, issue.project_id
1163 # Keep fixed_version
1163 # Keep fixed_version
1164 assert_equal 4, issue.fixed_version_id
1164 assert_equal 4, issue.fixed_version_id
1165 end
1165 end
1166
1166
1167 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1167 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1168 issue = Issue.find(1)
1168 issue = Issue.find(1)
1169 issue.update_attribute(:fixed_version_id, 1)
1169 issue.update_attribute(:fixed_version_id, 1)
1170 issue.project = Project.find(5)
1170 issue.project = Project.find(5)
1171 assert issue.save
1171 assert issue.save
1172 issue.reload
1172 issue.reload
1173 assert_equal 5, issue.project_id
1173 assert_equal 5, issue.project_id
1174 # Cleared fixed_version
1174 # Cleared fixed_version
1175 assert_equal nil, issue.fixed_version
1175 assert_equal nil, issue.fixed_version
1176 end
1176 end
1177
1177
1178 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1178 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1179 issue = Issue.find(1)
1179 issue = Issue.find(1)
1180 issue.update_attribute(:fixed_version_id, 7)
1180 issue.update_attribute(:fixed_version_id, 7)
1181 issue.project = Project.find(2)
1181 issue.project = Project.find(2)
1182 assert issue.save
1182 assert issue.save
1183 issue.reload
1183 issue.reload
1184 assert_equal 2, issue.project_id
1184 assert_equal 2, issue.project_id
1185 # Keep fixed_version
1185 # Keep fixed_version
1186 assert_equal 7, issue.fixed_version_id
1186 assert_equal 7, issue.fixed_version_id
1187 end
1187 end
1188
1188
1189 def test_move_to_another_project_should_keep_parent_if_valid
1189 def test_move_to_another_project_should_keep_parent_if_valid
1190 issue = Issue.find(1)
1190 issue = Issue.find(1)
1191 issue.update_attribute(:parent_issue_id, 2)
1191 issue.update_attribute(:parent_issue_id, 2)
1192 issue.project = Project.find(3)
1192 issue.project = Project.find(3)
1193 assert issue.save
1193 assert issue.save
1194 issue.reload
1194 issue.reload
1195 assert_equal 2, issue.parent_id
1195 assert_equal 2, issue.parent_id
1196 end
1196 end
1197
1197
1198 def test_move_to_another_project_should_clear_parent_if_not_valid
1198 def test_move_to_another_project_should_clear_parent_if_not_valid
1199 issue = Issue.find(1)
1199 issue = Issue.find(1)
1200 issue.update_attribute(:parent_issue_id, 2)
1200 issue.update_attribute(:parent_issue_id, 2)
1201 issue.project = Project.find(2)
1201 issue.project = Project.find(2)
1202 assert issue.save
1202 assert issue.save
1203 issue.reload
1203 issue.reload
1204 assert_nil issue.parent_id
1204 assert_nil issue.parent_id
1205 end
1205 end
1206
1206
1207 def test_move_to_another_project_with_disabled_tracker
1207 def test_move_to_another_project_with_disabled_tracker
1208 issue = Issue.find(1)
1208 issue = Issue.find(1)
1209 target = Project.find(2)
1209 target = Project.find(2)
1210 target.tracker_ids = [3]
1210 target.tracker_ids = [3]
1211 target.save
1211 target.save
1212 issue.project = target
1212 issue.project = target
1213 assert issue.save
1213 assert issue.save
1214 issue.reload
1214 issue.reload
1215 assert_equal 2, issue.project_id
1215 assert_equal 2, issue.project_id
1216 assert_equal 3, issue.tracker_id
1216 assert_equal 3, issue.tracker_id
1217 end
1217 end
1218
1218
1219 def test_copy_to_the_same_project
1219 def test_copy_to_the_same_project
1220 issue = Issue.find(1)
1220 issue = Issue.find(1)
1221 copy = issue.copy
1221 copy = issue.copy
1222 assert_difference 'Issue.count' do
1222 assert_difference 'Issue.count' do
1223 copy.save!
1223 copy.save!
1224 end
1224 end
1225 assert_kind_of Issue, copy
1225 assert_kind_of Issue, copy
1226 assert_equal issue.project, copy.project
1226 assert_equal issue.project, copy.project
1227 assert_equal "125", copy.custom_value_for(2).value
1227 assert_equal "125", copy.custom_value_for(2).value
1228 end
1228 end
1229
1229
1230 def test_copy_to_another_project_and_tracker
1230 def test_copy_to_another_project_and_tracker
1231 issue = Issue.find(1)
1231 issue = Issue.find(1)
1232 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1232 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1233 assert_difference 'Issue.count' do
1233 assert_difference 'Issue.count' do
1234 copy.save!
1234 copy.save!
1235 end
1235 end
1236 copy.reload
1236 copy.reload
1237 assert_kind_of Issue, copy
1237 assert_kind_of Issue, copy
1238 assert_equal Project.find(3), copy.project
1238 assert_equal Project.find(3), copy.project
1239 assert_equal Tracker.find(2), copy.tracker
1239 assert_equal Tracker.find(2), copy.tracker
1240 # Custom field #2 is not associated with target tracker
1240 # Custom field #2 is not associated with target tracker
1241 assert_nil copy.custom_value_for(2)
1241 assert_nil copy.custom_value_for(2)
1242 end
1242 end
1243
1243
1244 test "#copy should not create a journal" do
1244 test "#copy should not create a journal" do
1245 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1245 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1246 copy.save!
1246 copy.save!
1247 assert_equal 0, copy.reload.journals.size
1247 assert_equal 0, copy.reload.journals.size
1248 end
1248 end
1249
1249
1250 test "#copy should allow assigned_to changes" do
1250 test "#copy should allow assigned_to changes" do
1251 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1251 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1252 assert_equal 3, copy.assigned_to_id
1252 assert_equal 3, copy.assigned_to_id
1253 end
1253 end
1254
1254
1255 test "#copy should allow status changes" do
1255 test "#copy should allow status changes" do
1256 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1256 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1257 assert_equal 2, copy.status_id
1257 assert_equal 2, copy.status_id
1258 end
1258 end
1259
1259
1260 test "#copy should allow start date changes" do
1260 test "#copy should allow start date changes" do
1261 date = Date.today
1261 date = Date.today
1262 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1262 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1263 assert_equal date, copy.start_date
1263 assert_equal date, copy.start_date
1264 end
1264 end
1265
1265
1266 test "#copy should allow due date changes" do
1266 test "#copy should allow due date changes" do
1267 date = Date.today
1267 date = Date.today
1268 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1268 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1269 assert_equal date, copy.due_date
1269 assert_equal date, copy.due_date
1270 end
1270 end
1271
1271
1272 test "#copy should set current user as author" do
1272 test "#copy should set current user as author" do
1273 User.current = User.find(9)
1273 User.current = User.find(9)
1274 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1274 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1275 assert_equal User.current, copy.author
1275 assert_equal User.current, copy.author
1276 end
1276 end
1277
1277
1278 test "#copy should create a journal with notes" do
1278 test "#copy should create a journal with notes" do
1279 date = Date.today
1279 date = Date.today
1280 notes = "Notes added when copying"
1280 notes = "Notes added when copying"
1281 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1281 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1282 copy.init_journal(User.current, notes)
1282 copy.init_journal(User.current, notes)
1283 copy.save!
1283 copy.save!
1284
1284
1285 assert_equal 1, copy.journals.size
1285 assert_equal 1, copy.journals.size
1286 journal = copy.journals.first
1286 journal = copy.journals.first
1287 assert_equal 0, journal.details.size
1287 assert_equal 0, journal.details.size
1288 assert_equal notes, journal.notes
1288 assert_equal notes, journal.notes
1289 end
1289 end
1290
1290
1291 def test_valid_parent_project
1291 def test_valid_parent_project
1292 issue = Issue.find(1)
1292 issue = Issue.find(1)
1293 issue_in_same_project = Issue.find(2)
1293 issue_in_same_project = Issue.find(2)
1294 issue_in_child_project = Issue.find(5)
1294 issue_in_child_project = Issue.find(5)
1295 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1295 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1296 issue_in_other_child_project = Issue.find(6)
1296 issue_in_other_child_project = Issue.find(6)
1297 issue_in_different_tree = Issue.find(4)
1297 issue_in_different_tree = Issue.find(4)
1298
1298
1299 with_settings :cross_project_subtasks => '' do
1299 with_settings :cross_project_subtasks => '' do
1300 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1300 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1301 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1301 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1302 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1302 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1303 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1303 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1304 end
1304 end
1305
1305
1306 with_settings :cross_project_subtasks => 'system' do
1306 with_settings :cross_project_subtasks => 'system' do
1307 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1307 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1308 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1308 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1309 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1309 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1310 end
1310 end
1311
1311
1312 with_settings :cross_project_subtasks => 'tree' do
1312 with_settings :cross_project_subtasks => 'tree' do
1313 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1313 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1314 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1314 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1315 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1315 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1316 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1316 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1317
1317
1318 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1318 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1319 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1319 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1320 end
1320 end
1321
1321
1322 with_settings :cross_project_subtasks => 'descendants' do
1322 with_settings :cross_project_subtasks => 'descendants' do
1323 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1323 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1324 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1324 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1325 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1325 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1326 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1326 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1327
1327
1328 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1328 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1329 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1329 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1330 end
1330 end
1331 end
1331 end
1332
1332
1333 def test_recipients_should_include_previous_assignee
1333 def test_recipients_should_include_previous_assignee
1334 user = User.find(3)
1334 user = User.find(3)
1335 user.members.update_all ["mail_notification = ?", false]
1335 user.members.update_all ["mail_notification = ?", false]
1336 user.update_attribute :mail_notification, 'only_assigned'
1336 user.update_attribute :mail_notification, 'only_assigned'
1337
1337
1338 issue = Issue.find(2)
1338 issue = Issue.find(2)
1339 issue.assigned_to = nil
1339 issue.assigned_to = nil
1340 assert_include user.mail, issue.recipients
1340 assert_include user.mail, issue.recipients
1341 issue.save!
1341 issue.save!
1342 assert !issue.recipients.include?(user.mail)
1342 assert !issue.recipients.include?(user.mail)
1343 end
1343 end
1344
1344
1345 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1345 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1346 issue = Issue.find(12)
1346 issue = Issue.find(12)
1347 assert issue.recipients.include?(issue.author.mail)
1347 assert issue.recipients.include?(issue.author.mail)
1348 # copy the issue to a private project
1348 # copy the issue to a private project
1349 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1349 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1350 # author is not a member of project anymore
1350 # author is not a member of project anymore
1351 assert !copy.recipients.include?(copy.author.mail)
1351 assert !copy.recipients.include?(copy.author.mail)
1352 end
1352 end
1353
1353
1354 def test_recipients_should_include_the_assigned_group_members
1354 def test_recipients_should_include_the_assigned_group_members
1355 group_member = User.generate!
1355 group_member = User.generate!
1356 group = Group.generate!
1356 group = Group.generate!
1357 group.users << group_member
1357 group.users << group_member
1358
1358
1359 issue = Issue.find(12)
1359 issue = Issue.find(12)
1360 issue.assigned_to = group
1360 issue.assigned_to = group
1361 assert issue.recipients.include?(group_member.mail)
1361 assert issue.recipients.include?(group_member.mail)
1362 end
1362 end
1363
1363
1364 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1364 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1365 user = User.find(3)
1365 user = User.find(3)
1366 issue = Issue.find(9)
1366 issue = Issue.find(9)
1367 Watcher.create!(:user => user, :watchable => issue)
1367 Watcher.create!(:user => user, :watchable => issue)
1368 assert issue.watched_by?(user)
1368 assert issue.watched_by?(user)
1369 assert !issue.watcher_recipients.include?(user.mail)
1369 assert !issue.watcher_recipients.include?(user.mail)
1370 end
1370 end
1371
1371
1372 def test_issue_destroy
1372 def test_issue_destroy
1373 Issue.find(1).destroy
1373 Issue.find(1).destroy
1374 assert_nil Issue.find_by_id(1)
1374 assert_nil Issue.find_by_id(1)
1375 assert_nil TimeEntry.find_by_issue_id(1)
1375 assert_nil TimeEntry.find_by_issue_id(1)
1376 end
1376 end
1377
1377
1378 def test_destroying_a_deleted_issue_should_not_raise_an_error
1378 def test_destroying_a_deleted_issue_should_not_raise_an_error
1379 issue = Issue.find(1)
1379 issue = Issue.find(1)
1380 Issue.find(1).destroy
1380 Issue.find(1).destroy
1381
1381
1382 assert_nothing_raised do
1382 assert_nothing_raised do
1383 assert_no_difference 'Issue.count' do
1383 assert_no_difference 'Issue.count' do
1384 issue.destroy
1384 issue.destroy
1385 end
1385 end
1386 assert issue.destroyed?
1386 assert issue.destroyed?
1387 end
1387 end
1388 end
1388 end
1389
1389
1390 def test_destroying_a_stale_issue_should_not_raise_an_error
1390 def test_destroying_a_stale_issue_should_not_raise_an_error
1391 issue = Issue.find(1)
1391 issue = Issue.find(1)
1392 Issue.find(1).update_attribute :subject, "Updated"
1392 Issue.find(1).update_attribute :subject, "Updated"
1393
1393
1394 assert_nothing_raised do
1394 assert_nothing_raised do
1395 assert_difference 'Issue.count', -1 do
1395 assert_difference 'Issue.count', -1 do
1396 issue.destroy
1396 issue.destroy
1397 end
1397 end
1398 assert issue.destroyed?
1398 assert issue.destroyed?
1399 end
1399 end
1400 end
1400 end
1401
1401
1402 def test_blocked
1402 def test_blocked
1403 blocked_issue = Issue.find(9)
1403 blocked_issue = Issue.find(9)
1404 blocking_issue = Issue.find(10)
1404 blocking_issue = Issue.find(10)
1405
1405
1406 assert blocked_issue.blocked?
1406 assert blocked_issue.blocked?
1407 assert !blocking_issue.blocked?
1407 assert !blocking_issue.blocked?
1408 end
1408 end
1409
1409
1410 def test_blocked_issues_dont_allow_closed_statuses
1410 def test_blocked_issues_dont_allow_closed_statuses
1411 blocked_issue = Issue.find(9)
1411 blocked_issue = Issue.find(9)
1412
1412
1413 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1413 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1414 assert !allowed_statuses.empty?
1414 assert !allowed_statuses.empty?
1415 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1415 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1416 assert closed_statuses.empty?
1416 assert closed_statuses.empty?
1417 end
1417 end
1418
1418
1419 def test_unblocked_issues_allow_closed_statuses
1419 def test_unblocked_issues_allow_closed_statuses
1420 blocking_issue = Issue.find(10)
1420 blocking_issue = Issue.find(10)
1421
1421
1422 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1422 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1423 assert !allowed_statuses.empty?
1423 assert !allowed_statuses.empty?
1424 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1424 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1425 assert !closed_statuses.empty?
1425 assert !closed_statuses.empty?
1426 end
1426 end
1427
1427
1428 def test_reschedule_an_issue_without_dates
1428 def test_reschedule_an_issue_without_dates
1429 with_settings :non_working_week_days => [] do
1429 with_settings :non_working_week_days => [] do
1430 issue = Issue.new(:start_date => nil, :due_date => nil)
1430 issue = Issue.new(:start_date => nil, :due_date => nil)
1431 issue.reschedule_on '2012-10-09'.to_date
1431 issue.reschedule_on '2012-10-09'.to_date
1432 assert_equal '2012-10-09'.to_date, issue.start_date
1432 assert_equal '2012-10-09'.to_date, issue.start_date
1433 assert_equal '2012-10-09'.to_date, issue.due_date
1433 assert_equal '2012-10-09'.to_date, issue.due_date
1434 end
1434 end
1435
1435
1436 with_settings :non_working_week_days => %w(6 7) do
1436 with_settings :non_working_week_days => %w(6 7) do
1437 issue = Issue.new(:start_date => nil, :due_date => nil)
1437 issue = Issue.new(:start_date => nil, :due_date => nil)
1438 issue.reschedule_on '2012-10-09'.to_date
1438 issue.reschedule_on '2012-10-09'.to_date
1439 assert_equal '2012-10-09'.to_date, issue.start_date
1439 assert_equal '2012-10-09'.to_date, issue.start_date
1440 assert_equal '2012-10-09'.to_date, issue.due_date
1440 assert_equal '2012-10-09'.to_date, issue.due_date
1441
1441
1442 issue = Issue.new(:start_date => nil, :due_date => nil)
1442 issue = Issue.new(:start_date => nil, :due_date => nil)
1443 issue.reschedule_on '2012-10-13'.to_date
1443 issue.reschedule_on '2012-10-13'.to_date
1444 assert_equal '2012-10-15'.to_date, issue.start_date
1444 assert_equal '2012-10-15'.to_date, issue.start_date
1445 assert_equal '2012-10-15'.to_date, issue.due_date
1445 assert_equal '2012-10-15'.to_date, issue.due_date
1446 end
1446 end
1447 end
1447 end
1448
1448
1449 def test_reschedule_an_issue_with_start_date
1449 def test_reschedule_an_issue_with_start_date
1450 with_settings :non_working_week_days => [] do
1450 with_settings :non_working_week_days => [] do
1451 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1451 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1452 issue.reschedule_on '2012-10-13'.to_date
1452 issue.reschedule_on '2012-10-13'.to_date
1453 assert_equal '2012-10-13'.to_date, issue.start_date
1453 assert_equal '2012-10-13'.to_date, issue.start_date
1454 assert_equal '2012-10-13'.to_date, issue.due_date
1454 assert_equal '2012-10-13'.to_date, issue.due_date
1455 end
1455 end
1456
1456
1457 with_settings :non_working_week_days => %w(6 7) do
1457 with_settings :non_working_week_days => %w(6 7) do
1458 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1458 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1459 issue.reschedule_on '2012-10-11'.to_date
1459 issue.reschedule_on '2012-10-11'.to_date
1460 assert_equal '2012-10-11'.to_date, issue.start_date
1460 assert_equal '2012-10-11'.to_date, issue.start_date
1461 assert_equal '2012-10-11'.to_date, issue.due_date
1461 assert_equal '2012-10-11'.to_date, issue.due_date
1462
1462
1463 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1463 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1464 issue.reschedule_on '2012-10-13'.to_date
1464 issue.reschedule_on '2012-10-13'.to_date
1465 assert_equal '2012-10-15'.to_date, issue.start_date
1465 assert_equal '2012-10-15'.to_date, issue.start_date
1466 assert_equal '2012-10-15'.to_date, issue.due_date
1466 assert_equal '2012-10-15'.to_date, issue.due_date
1467 end
1467 end
1468 end
1468 end
1469
1469
1470 def test_reschedule_an_issue_with_start_and_due_dates
1470 def test_reschedule_an_issue_with_start_and_due_dates
1471 with_settings :non_working_week_days => [] do
1471 with_settings :non_working_week_days => [] do
1472 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1472 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1473 issue.reschedule_on '2012-10-13'.to_date
1473 issue.reschedule_on '2012-10-13'.to_date
1474 assert_equal '2012-10-13'.to_date, issue.start_date
1474 assert_equal '2012-10-13'.to_date, issue.start_date
1475 assert_equal '2012-10-19'.to_date, issue.due_date
1475 assert_equal '2012-10-19'.to_date, issue.due_date
1476 end
1476 end
1477
1477
1478 with_settings :non_working_week_days => %w(6 7) do
1478 with_settings :non_working_week_days => %w(6 7) do
1479 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1479 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1480 issue.reschedule_on '2012-10-11'.to_date
1480 issue.reschedule_on '2012-10-11'.to_date
1481 assert_equal '2012-10-11'.to_date, issue.start_date
1481 assert_equal '2012-10-11'.to_date, issue.start_date
1482 assert_equal '2012-10-23'.to_date, issue.due_date
1482 assert_equal '2012-10-23'.to_date, issue.due_date
1483
1483
1484 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1484 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1485 issue.reschedule_on '2012-10-13'.to_date
1485 issue.reschedule_on '2012-10-13'.to_date
1486 assert_equal '2012-10-15'.to_date, issue.start_date
1486 assert_equal '2012-10-15'.to_date, issue.start_date
1487 assert_equal '2012-10-25'.to_date, issue.due_date
1487 assert_equal '2012-10-25'.to_date, issue.due_date
1488 end
1488 end
1489 end
1489 end
1490
1490
1491 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1491 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1492 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1492 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1493 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1493 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1494 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1494 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1495 :relation_type => IssueRelation::TYPE_PRECEDES)
1495 :relation_type => IssueRelation::TYPE_PRECEDES)
1496 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1496 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1497
1497
1498 issue1.reload
1498 issue1.reload
1499 issue1.due_date = '2012-10-23'
1499 issue1.due_date = '2012-10-23'
1500 issue1.save!
1500 issue1.save!
1501 issue2.reload
1501 issue2.reload
1502 assert_equal Date.parse('2012-10-24'), issue2.start_date
1502 assert_equal Date.parse('2012-10-24'), issue2.start_date
1503 assert_equal Date.parse('2012-10-26'), issue2.due_date
1503 assert_equal Date.parse('2012-10-26'), issue2.due_date
1504 end
1504 end
1505
1505
1506 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1506 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1507 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1507 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1508 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1508 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1509 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1509 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1510 :relation_type => IssueRelation::TYPE_PRECEDES)
1510 :relation_type => IssueRelation::TYPE_PRECEDES)
1511 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1511 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1512
1512
1513 issue1.reload
1513 issue1.reload
1514 issue1.start_date = '2012-09-17'
1514 issue1.start_date = '2012-09-17'
1515 issue1.due_date = '2012-09-18'
1515 issue1.due_date = '2012-09-18'
1516 issue1.save!
1516 issue1.save!
1517 issue2.reload
1517 issue2.reload
1518 assert_equal Date.parse('2012-09-19'), issue2.start_date
1518 assert_equal Date.parse('2012-09-19'), issue2.start_date
1519 assert_equal Date.parse('2012-09-21'), issue2.due_date
1519 assert_equal Date.parse('2012-09-21'), issue2.due_date
1520 end
1520 end
1521
1521
1522 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1522 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1523 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1523 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1524 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1524 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1525 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1525 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1526 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1526 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1527 :relation_type => IssueRelation::TYPE_PRECEDES)
1527 :relation_type => IssueRelation::TYPE_PRECEDES)
1528 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1528 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1529 :relation_type => IssueRelation::TYPE_PRECEDES)
1529 :relation_type => IssueRelation::TYPE_PRECEDES)
1530 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1530 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1531
1531
1532 issue1.reload
1532 issue1.reload
1533 issue1.start_date = '2012-09-17'
1533 issue1.start_date = '2012-09-17'
1534 issue1.due_date = '2012-09-18'
1534 issue1.due_date = '2012-09-18'
1535 issue1.save!
1535 issue1.save!
1536 issue2.reload
1536 issue2.reload
1537 # Issue 2 must start after Issue 3
1537 # Issue 2 must start after Issue 3
1538 assert_equal Date.parse('2012-10-03'), issue2.start_date
1538 assert_equal Date.parse('2012-10-03'), issue2.start_date
1539 assert_equal Date.parse('2012-10-05'), issue2.due_date
1539 assert_equal Date.parse('2012-10-05'), issue2.due_date
1540 end
1540 end
1541
1541
1542 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1542 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1543 with_settings :non_working_week_days => [] do
1543 with_settings :non_working_week_days => [] do
1544 stale = Issue.find(1)
1544 stale = Issue.find(1)
1545 issue = Issue.find(1)
1545 issue = Issue.find(1)
1546 issue.subject = "Updated"
1546 issue.subject = "Updated"
1547 issue.save!
1547 issue.save!
1548 date = 10.days.from_now.to_date
1548 date = 10.days.from_now.to_date
1549 assert_nothing_raised do
1549 assert_nothing_raised do
1550 stale.reschedule_on!(date)
1550 stale.reschedule_on!(date)
1551 end
1551 end
1552 assert_equal date, stale.reload.start_date
1552 assert_equal date, stale.reload.start_date
1553 end
1553 end
1554 end
1554 end
1555
1555
1556 def test_child_issue_should_consider_parent_soonest_start_on_create
1556 def test_child_issue_should_consider_parent_soonest_start_on_create
1557 set_language_if_valid 'en'
1557 set_language_if_valid 'en'
1558 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1558 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1559 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1559 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1560 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1560 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1561 :relation_type => IssueRelation::TYPE_PRECEDES)
1561 :relation_type => IssueRelation::TYPE_PRECEDES)
1562 issue1.reload
1562 issue1.reload
1563 issue2.reload
1563 issue2.reload
1564 assert_equal Date.parse('2012-10-18'), issue2.start_date
1564 assert_equal Date.parse('2012-10-18'), issue2.start_date
1565
1565
1566 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1566 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1567 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1567 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1568 assert !child.valid?
1568 assert !child.valid?
1569 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1569 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1570 assert_equal Date.parse('2012-10-18'), child.soonest_start
1570 assert_equal Date.parse('2012-10-18'), child.soonest_start
1571 child.start_date = '2012-10-18'
1571 child.start_date = '2012-10-18'
1572 assert child.save
1572 assert child.save
1573 end
1573 end
1574
1574
1575 def test_setting_parent_to_a_dependent_issue_should_not_validate
1575 def test_setting_parent_to_a_dependent_issue_should_not_validate
1576 set_language_if_valid 'en'
1576 set_language_if_valid 'en'
1577 issue1 = Issue.generate!
1577 issue1 = Issue.generate!
1578 issue2 = Issue.generate!
1578 issue2 = Issue.generate!
1579 issue3 = Issue.generate!
1579 issue3 = Issue.generate!
1580 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1580 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1581 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1581 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1582 issue3.reload
1582 issue3.reload
1583 issue3.parent_issue_id = issue2.id
1583 issue3.parent_issue_id = issue2.id
1584 assert !issue3.valid?
1584 assert !issue3.valid?
1585 assert_include 'Parent task is invalid', issue3.errors.full_messages
1585 assert_include 'Parent task is invalid', issue3.errors.full_messages
1586 end
1586 end
1587
1587
1588 def test_setting_parent_should_not_allow_circular_dependency
1588 def test_setting_parent_should_not_allow_circular_dependency
1589 set_language_if_valid 'en'
1589 set_language_if_valid 'en'
1590 issue1 = Issue.generate!
1590 issue1 = Issue.generate!
1591 issue2 = Issue.generate!
1591 issue2 = Issue.generate!
1592 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1592 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1593 issue3 = Issue.generate!
1593 issue3 = Issue.generate!
1594 issue2.reload
1594 issue2.reload
1595 issue2.parent_issue_id = issue3.id
1595 issue2.parent_issue_id = issue3.id
1596 issue2.save!
1596 issue2.save!
1597 issue4 = Issue.generate!
1597 issue4 = Issue.generate!
1598 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1598 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1599 issue4.reload
1599 issue4.reload
1600 issue4.parent_issue_id = issue1.id
1600 issue4.parent_issue_id = issue1.id
1601 assert !issue4.valid?
1601 assert !issue4.valid?
1602 assert_include 'Parent task is invalid', issue4.errors.full_messages
1602 assert_include 'Parent task is invalid', issue4.errors.full_messages
1603 end
1603 end
1604
1604
1605 def test_overdue
1605 def test_overdue
1606 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1606 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1607 assert !Issue.new(:due_date => Date.today).overdue?
1607 assert !Issue.new(:due_date => Date.today).overdue?
1608 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1608 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1609 assert !Issue.new(:due_date => nil).overdue?
1609 assert !Issue.new(:due_date => nil).overdue?
1610 assert !Issue.new(:due_date => 1.day.ago.to_date,
1610 assert !Issue.new(:due_date => 1.day.ago.to_date,
1611 :status => IssueStatus.where(:is_closed => true).first
1611 :status => IssueStatus.where(:is_closed => true).first
1612 ).overdue?
1612 ).overdue?
1613 end
1613 end
1614
1614
1615 test "#behind_schedule? should be false if the issue has no start_date" do
1615 test "#behind_schedule? should be false if the issue has no start_date" do
1616 assert !Issue.new(:start_date => nil,
1616 assert !Issue.new(:start_date => nil,
1617 :due_date => 1.day.from_now.to_date,
1617 :due_date => 1.day.from_now.to_date,
1618 :done_ratio => 0).behind_schedule?
1618 :done_ratio => 0).behind_schedule?
1619 end
1619 end
1620
1620
1621 test "#behind_schedule? should be false if the issue has no end_date" do
1621 test "#behind_schedule? should be false if the issue has no end_date" do
1622 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1622 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1623 :due_date => nil,
1623 :due_date => nil,
1624 :done_ratio => 0).behind_schedule?
1624 :done_ratio => 0).behind_schedule?
1625 end
1625 end
1626
1626
1627 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1627 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1628 assert !Issue.new(:start_date => 50.days.ago.to_date,
1628 assert !Issue.new(:start_date => 50.days.ago.to_date,
1629 :due_date => 50.days.from_now.to_date,
1629 :due_date => 50.days.from_now.to_date,
1630 :done_ratio => 90).behind_schedule?
1630 :done_ratio => 90).behind_schedule?
1631 end
1631 end
1632
1632
1633 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1633 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1634 assert Issue.new(:start_date => 1.day.ago.to_date,
1634 assert Issue.new(:start_date => 1.day.ago.to_date,
1635 :due_date => 1.day.from_now.to_date,
1635 :due_date => 1.day.from_now.to_date,
1636 :done_ratio => 0).behind_schedule?
1636 :done_ratio => 0).behind_schedule?
1637 end
1637 end
1638
1638
1639 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1639 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1640 assert Issue.new(:start_date => 100.days.ago.to_date,
1640 assert Issue.new(:start_date => 100.days.ago.to_date,
1641 :due_date => Date.today,
1641 :due_date => Date.today,
1642 :done_ratio => 90).behind_schedule?
1642 :done_ratio => 90).behind_schedule?
1643 end
1643 end
1644
1644
1645 test "#assignable_users should be Users" do
1645 test "#assignable_users should be Users" do
1646 assert_kind_of User, Issue.find(1).assignable_users.first
1646 assert_kind_of User, Issue.find(1).assignable_users.first
1647 end
1647 end
1648
1648
1649 test "#assignable_users should include the issue author" do
1649 test "#assignable_users should include the issue author" do
1650 non_project_member = User.generate!
1650 non_project_member = User.generate!
1651 issue = Issue.generate!(:author => non_project_member)
1651 issue = Issue.generate!(:author => non_project_member)
1652
1652
1653 assert issue.assignable_users.include?(non_project_member)
1653 assert issue.assignable_users.include?(non_project_member)
1654 end
1654 end
1655
1655
1656 test "#assignable_users should include the current assignee" do
1656 test "#assignable_users should include the current assignee" do
1657 user = User.generate!
1657 user = User.generate!
1658 issue = Issue.generate!(:assigned_to => user)
1658 issue = Issue.generate!(:assigned_to => user)
1659 user.lock!
1659 user.lock!
1660
1660
1661 assert Issue.find(issue.id).assignable_users.include?(user)
1661 assert Issue.find(issue.id).assignable_users.include?(user)
1662 end
1662 end
1663
1663
1664 test "#assignable_users should not show the issue author twice" do
1664 test "#assignable_users should not show the issue author twice" do
1665 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1665 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1666 assert_equal 2, assignable_user_ids.length
1666 assert_equal 2, assignable_user_ids.length
1667
1667
1668 assignable_user_ids.each do |user_id|
1668 assignable_user_ids.each do |user_id|
1669 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1669 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1670 "User #{user_id} appears more or less than once"
1670 "User #{user_id} appears more or less than once"
1671 end
1671 end
1672 end
1672 end
1673
1673
1674 test "#assignable_users with issue_group_assignment should include groups" do
1674 test "#assignable_users with issue_group_assignment should include groups" do
1675 issue = Issue.new(:project => Project.find(2))
1675 issue = Issue.new(:project => Project.find(2))
1676
1676
1677 with_settings :issue_group_assignment => '1' do
1677 with_settings :issue_group_assignment => '1' do
1678 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1678 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1679 assert issue.assignable_users.include?(Group.find(11))
1679 assert issue.assignable_users.include?(Group.find(11))
1680 end
1680 end
1681 end
1681 end
1682
1682
1683 test "#assignable_users without issue_group_assignment should not include groups" do
1683 test "#assignable_users without issue_group_assignment should not include groups" do
1684 issue = Issue.new(:project => Project.find(2))
1684 issue = Issue.new(:project => Project.find(2))
1685
1685
1686 with_settings :issue_group_assignment => '0' do
1686 with_settings :issue_group_assignment => '0' do
1687 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1687 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1688 assert !issue.assignable_users.include?(Group.find(11))
1688 assert !issue.assignable_users.include?(Group.find(11))
1689 end
1689 end
1690 end
1690 end
1691
1691
1692 def test_create_should_send_email_notification
1692 def test_create_should_send_email_notification
1693 ActionMailer::Base.deliveries.clear
1693 ActionMailer::Base.deliveries.clear
1694 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1694 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1695 :author_id => 3, :status_id => 1,
1695 :author_id => 3, :status_id => 1,
1696 :priority => IssuePriority.all.first,
1696 :priority => IssuePriority.all.first,
1697 :subject => 'test_create', :estimated_hours => '1:30')
1697 :subject => 'test_create', :estimated_hours => '1:30')
1698 with_settings :notified_events => %w(issue_added) do
1698 with_settings :notified_events => %w(issue_added) do
1699 assert issue.save
1699 assert issue.save
1700 assert_equal 1, ActionMailer::Base.deliveries.size
1700 assert_equal 1, ActionMailer::Base.deliveries.size
1701 end
1701 end
1702 end
1702 end
1703
1703
1704 def test_create_should_not_send_email_notification_with_no_setting
1705 ActionMailer::Base.deliveries.clear
1706 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1707 :author_id => 3, :status_id => 1,
1708 :priority => IssuePriority.all.first,
1709 :subject => 'test_create', :estimated_hours => '1:30')
1710 with_settings :notified_events => [] do
1711 assert issue.save
1712 assert_equal 0, ActionMailer::Base.deliveries.size
1713 end
1714 end
1715
1704 def test_stale_issue_should_not_send_email_notification
1716 def test_stale_issue_should_not_send_email_notification
1705 ActionMailer::Base.deliveries.clear
1717 ActionMailer::Base.deliveries.clear
1706 issue = Issue.find(1)
1718 issue = Issue.find(1)
1707 stale = Issue.find(1)
1719 stale = Issue.find(1)
1708
1720
1709 issue.init_journal(User.find(1))
1721 issue.init_journal(User.find(1))
1710 issue.subject = 'Subjet update'
1722 issue.subject = 'Subjet update'
1711 with_settings :notified_events => %w(issue_updated) do
1723 with_settings :notified_events => %w(issue_updated) do
1712 assert issue.save
1724 assert issue.save
1713 assert_equal 1, ActionMailer::Base.deliveries.size
1725 assert_equal 1, ActionMailer::Base.deliveries.size
1714 ActionMailer::Base.deliveries.clear
1726 ActionMailer::Base.deliveries.clear
1715
1727
1716 stale.init_journal(User.find(1))
1728 stale.init_journal(User.find(1))
1717 stale.subject = 'Another subjet update'
1729 stale.subject = 'Another subjet update'
1718 assert_raise ActiveRecord::StaleObjectError do
1730 assert_raise ActiveRecord::StaleObjectError do
1719 stale.save
1731 stale.save
1720 end
1732 end
1721 assert ActionMailer::Base.deliveries.empty?
1733 assert ActionMailer::Base.deliveries.empty?
1722 end
1734 end
1723 end
1735 end
1724
1736
1725 def test_journalized_description
1737 def test_journalized_description
1726 IssueCustomField.delete_all
1738 IssueCustomField.delete_all
1727
1739
1728 i = Issue.first
1740 i = Issue.first
1729 old_description = i.description
1741 old_description = i.description
1730 new_description = "This is the new description"
1742 new_description = "This is the new description"
1731
1743
1732 i.init_journal(User.find(2))
1744 i.init_journal(User.find(2))
1733 i.description = new_description
1745 i.description = new_description
1734 assert_difference 'Journal.count', 1 do
1746 assert_difference 'Journal.count', 1 do
1735 assert_difference 'JournalDetail.count', 1 do
1747 assert_difference 'JournalDetail.count', 1 do
1736 i.save!
1748 i.save!
1737 end
1749 end
1738 end
1750 end
1739
1751
1740 detail = JournalDetail.first(:order => 'id DESC')
1752 detail = JournalDetail.first(:order => 'id DESC')
1741 assert_equal i, detail.journal.journalized
1753 assert_equal i, detail.journal.journalized
1742 assert_equal 'attr', detail.property
1754 assert_equal 'attr', detail.property
1743 assert_equal 'description', detail.prop_key
1755 assert_equal 'description', detail.prop_key
1744 assert_equal old_description, detail.old_value
1756 assert_equal old_description, detail.old_value
1745 assert_equal new_description, detail.value
1757 assert_equal new_description, detail.value
1746 end
1758 end
1747
1759
1748 def test_blank_descriptions_should_not_be_journalized
1760 def test_blank_descriptions_should_not_be_journalized
1749 IssueCustomField.delete_all
1761 IssueCustomField.delete_all
1750 Issue.update_all("description = NULL", "id=1")
1762 Issue.update_all("description = NULL", "id=1")
1751
1763
1752 i = Issue.find(1)
1764 i = Issue.find(1)
1753 i.init_journal(User.find(2))
1765 i.init_journal(User.find(2))
1754 i.subject = "blank description"
1766 i.subject = "blank description"
1755 i.description = "\r\n"
1767 i.description = "\r\n"
1756
1768
1757 assert_difference 'Journal.count', 1 do
1769 assert_difference 'Journal.count', 1 do
1758 assert_difference 'JournalDetail.count', 1 do
1770 assert_difference 'JournalDetail.count', 1 do
1759 i.save!
1771 i.save!
1760 end
1772 end
1761 end
1773 end
1762 end
1774 end
1763
1775
1764 def test_journalized_multi_custom_field
1776 def test_journalized_multi_custom_field
1765 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1777 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1766 :is_filter => true, :is_for_all => true,
1778 :is_filter => true, :is_for_all => true,
1767 :tracker_ids => [1],
1779 :tracker_ids => [1],
1768 :possible_values => ['value1', 'value2', 'value3'],
1780 :possible_values => ['value1', 'value2', 'value3'],
1769 :multiple => true)
1781 :multiple => true)
1770
1782
1771 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1783 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1772 :subject => 'Test', :author_id => 1)
1784 :subject => 'Test', :author_id => 1)
1773
1785
1774 assert_difference 'Journal.count' do
1786 assert_difference 'Journal.count' do
1775 assert_difference 'JournalDetail.count' do
1787 assert_difference 'JournalDetail.count' do
1776 issue.init_journal(User.first)
1788 issue.init_journal(User.first)
1777 issue.custom_field_values = {field.id => ['value1']}
1789 issue.custom_field_values = {field.id => ['value1']}
1778 issue.save!
1790 issue.save!
1779 end
1791 end
1780 assert_difference 'JournalDetail.count' do
1792 assert_difference 'JournalDetail.count' do
1781 issue.init_journal(User.first)
1793 issue.init_journal(User.first)
1782 issue.custom_field_values = {field.id => ['value1', 'value2']}
1794 issue.custom_field_values = {field.id => ['value1', 'value2']}
1783 issue.save!
1795 issue.save!
1784 end
1796 end
1785 assert_difference 'JournalDetail.count', 2 do
1797 assert_difference 'JournalDetail.count', 2 do
1786 issue.init_journal(User.first)
1798 issue.init_journal(User.first)
1787 issue.custom_field_values = {field.id => ['value3', 'value2']}
1799 issue.custom_field_values = {field.id => ['value3', 'value2']}
1788 issue.save!
1800 issue.save!
1789 end
1801 end
1790 assert_difference 'JournalDetail.count', 2 do
1802 assert_difference 'JournalDetail.count', 2 do
1791 issue.init_journal(User.first)
1803 issue.init_journal(User.first)
1792 issue.custom_field_values = {field.id => nil}
1804 issue.custom_field_values = {field.id => nil}
1793 issue.save!
1805 issue.save!
1794 end
1806 end
1795 end
1807 end
1796 end
1808 end
1797
1809
1798 def test_description_eol_should_be_normalized
1810 def test_description_eol_should_be_normalized
1799 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1811 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1800 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1812 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1801 end
1813 end
1802
1814
1803 def test_saving_twice_should_not_duplicate_journal_details
1815 def test_saving_twice_should_not_duplicate_journal_details
1804 i = Issue.first
1816 i = Issue.first
1805 i.init_journal(User.find(2), 'Some notes')
1817 i.init_journal(User.find(2), 'Some notes')
1806 # initial changes
1818 # initial changes
1807 i.subject = 'New subject'
1819 i.subject = 'New subject'
1808 i.done_ratio = i.done_ratio + 10
1820 i.done_ratio = i.done_ratio + 10
1809 assert_difference 'Journal.count' do
1821 assert_difference 'Journal.count' do
1810 assert i.save
1822 assert i.save
1811 end
1823 end
1812 # 1 more change
1824 # 1 more change
1813 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1825 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1814 assert_no_difference 'Journal.count' do
1826 assert_no_difference 'Journal.count' do
1815 assert_difference 'JournalDetail.count', 1 do
1827 assert_difference 'JournalDetail.count', 1 do
1816 i.save
1828 i.save
1817 end
1829 end
1818 end
1830 end
1819 # no more change
1831 # no more change
1820 assert_no_difference 'Journal.count' do
1832 assert_no_difference 'Journal.count' do
1821 assert_no_difference 'JournalDetail.count' do
1833 assert_no_difference 'JournalDetail.count' do
1822 i.save
1834 i.save
1823 end
1835 end
1824 end
1836 end
1825 end
1837 end
1826
1838
1827 def test_all_dependent_issues
1839 def test_all_dependent_issues
1828 IssueRelation.delete_all
1840 IssueRelation.delete_all
1829 assert IssueRelation.create!(:issue_from => Issue.find(1),
1841 assert IssueRelation.create!(:issue_from => Issue.find(1),
1830 :issue_to => Issue.find(2),
1842 :issue_to => Issue.find(2),
1831 :relation_type => IssueRelation::TYPE_PRECEDES)
1843 :relation_type => IssueRelation::TYPE_PRECEDES)
1832 assert IssueRelation.create!(:issue_from => Issue.find(2),
1844 assert IssueRelation.create!(:issue_from => Issue.find(2),
1833 :issue_to => Issue.find(3),
1845 :issue_to => Issue.find(3),
1834 :relation_type => IssueRelation::TYPE_PRECEDES)
1846 :relation_type => IssueRelation::TYPE_PRECEDES)
1835 assert IssueRelation.create!(:issue_from => Issue.find(3),
1847 assert IssueRelation.create!(:issue_from => Issue.find(3),
1836 :issue_to => Issue.find(8),
1848 :issue_to => Issue.find(8),
1837 :relation_type => IssueRelation::TYPE_PRECEDES)
1849 :relation_type => IssueRelation::TYPE_PRECEDES)
1838
1850
1839 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1851 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1840 end
1852 end
1841
1853
1842 def test_all_dependent_issues_with_subtask
1854 def test_all_dependent_issues_with_subtask
1843 IssueRelation.delete_all
1855 IssueRelation.delete_all
1844
1856
1845 project = Project.generate!(:name => "testproject")
1857 project = Project.generate!(:name => "testproject")
1846
1858
1847 parentIssue = Issue.generate!(:project => project)
1859 parentIssue = Issue.generate!(:project => project)
1848 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1860 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1849 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1861 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1850
1862
1851 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
1863 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
1852 end
1864 end
1853
1865
1854 def test_all_dependent_issues_does_not_include_self
1866 def test_all_dependent_issues_does_not_include_self
1855 IssueRelation.delete_all
1867 IssueRelation.delete_all
1856
1868
1857 project = Project.generate!(:name => "testproject")
1869 project = Project.generate!(:name => "testproject")
1858
1870
1859 parentIssue = Issue.generate!(:project => project)
1871 parentIssue = Issue.generate!(:project => project)
1860 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1872 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1861
1873
1862 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
1874 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
1863 end
1875 end
1864
1876
1865 def test_all_dependent_issues_with_parenttask_and_sibling
1877 def test_all_dependent_issues_with_parenttask_and_sibling
1866 IssueRelation.delete_all
1878 IssueRelation.delete_all
1867
1879
1868 project = Project.generate!(:name => "testproject")
1880 project = Project.generate!(:name => "testproject")
1869
1881
1870 parentIssue = Issue.generate!(:project => project)
1882 parentIssue = Issue.generate!(:project => project)
1871 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1883 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1872 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1884 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1873
1885
1874 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
1886 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
1875 end
1887 end
1876
1888
1877 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
1889 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
1878 IssueRelation.delete_all
1890 IssueRelation.delete_all
1879
1891
1880 project = Project.generate!(:name => "testproject")
1892 project = Project.generate!(:name => "testproject")
1881
1893
1882 parentIssue1 = Issue.generate!(:project => project)
1894 parentIssue1 = Issue.generate!(:project => project)
1883 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1895 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1884 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1896 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1885
1897
1886 parentIssue2 = Issue.generate!(:project => project)
1898 parentIssue2 = Issue.generate!(:project => project)
1887 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1899 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1888 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1900 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1889
1901
1890
1902
1891 assert IssueRelation.create(:issue_from => parentIssue1,
1903 assert IssueRelation.create(:issue_from => parentIssue1,
1892 :issue_to => childIssue2_2,
1904 :issue_to => childIssue2_2,
1893 :relation_type => IssueRelation::TYPE_BLOCKS)
1905 :relation_type => IssueRelation::TYPE_BLOCKS)
1894
1906
1895 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
1907 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
1896 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1908 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1897 end
1909 end
1898
1910
1899 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
1911 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
1900 IssueRelation.delete_all
1912 IssueRelation.delete_all
1901
1913
1902 project = Project.generate!(:name => "testproject")
1914 project = Project.generate!(:name => "testproject")
1903
1915
1904 parentIssue1 = Issue.generate!(:project => project)
1916 parentIssue1 = Issue.generate!(:project => project)
1905 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1917 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1906 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1918 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1907
1919
1908 parentIssue2 = Issue.generate!(:project => project)
1920 parentIssue2 = Issue.generate!(:project => project)
1909 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1921 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1910 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1922 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1911
1923
1912
1924
1913 assert IssueRelation.create(:issue_from => parentIssue1,
1925 assert IssueRelation.create(:issue_from => parentIssue1,
1914 :issue_to => parentIssue2,
1926 :issue_to => parentIssue2,
1915 :relation_type => IssueRelation::TYPE_BLOCKS)
1927 :relation_type => IssueRelation::TYPE_BLOCKS)
1916
1928
1917 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
1929 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
1918 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1930 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1919 end
1931 end
1920
1932
1921 def test_all_dependent_issues_with_transitive_relation
1933 def test_all_dependent_issues_with_transitive_relation
1922 IssueRelation.delete_all
1934 IssueRelation.delete_all
1923
1935
1924 project = Project.generate!(:name => "testproject")
1936 project = Project.generate!(:name => "testproject")
1925
1937
1926 parentIssue1 = Issue.generate!(:project => project)
1938 parentIssue1 = Issue.generate!(:project => project)
1927 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1939 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1928
1940
1929 parentIssue2 = Issue.generate!(:project => project)
1941 parentIssue2 = Issue.generate!(:project => project)
1930 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1942 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1931
1943
1932 independentIssue = Issue.generate!(:project => project)
1944 independentIssue = Issue.generate!(:project => project)
1933
1945
1934 assert IssueRelation.create(:issue_from => parentIssue1,
1946 assert IssueRelation.create(:issue_from => parentIssue1,
1935 :issue_to => childIssue2_1,
1947 :issue_to => childIssue2_1,
1936 :relation_type => IssueRelation::TYPE_RELATES)
1948 :relation_type => IssueRelation::TYPE_RELATES)
1937
1949
1938 assert IssueRelation.create(:issue_from => childIssue2_1,
1950 assert IssueRelation.create(:issue_from => childIssue2_1,
1939 :issue_to => independentIssue,
1951 :issue_to => independentIssue,
1940 :relation_type => IssueRelation::TYPE_RELATES)
1952 :relation_type => IssueRelation::TYPE_RELATES)
1941
1953
1942 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1954 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1943 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1955 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1944 end
1956 end
1945
1957
1946 def test_all_dependent_issues_with_transitive_relation2
1958 def test_all_dependent_issues_with_transitive_relation2
1947 IssueRelation.delete_all
1959 IssueRelation.delete_all
1948
1960
1949 project = Project.generate!(:name => "testproject")
1961 project = Project.generate!(:name => "testproject")
1950
1962
1951 parentIssue1 = Issue.generate!(:project => project)
1963 parentIssue1 = Issue.generate!(:project => project)
1952 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1964 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1953
1965
1954 parentIssue2 = Issue.generate!(:project => project)
1966 parentIssue2 = Issue.generate!(:project => project)
1955 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1967 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1956
1968
1957 independentIssue = Issue.generate!(:project => project)
1969 independentIssue = Issue.generate!(:project => project)
1958
1970
1959 assert IssueRelation.create(:issue_from => parentIssue1,
1971 assert IssueRelation.create(:issue_from => parentIssue1,
1960 :issue_to => independentIssue,
1972 :issue_to => independentIssue,
1961 :relation_type => IssueRelation::TYPE_RELATES)
1973 :relation_type => IssueRelation::TYPE_RELATES)
1962
1974
1963 assert IssueRelation.create(:issue_from => independentIssue,
1975 assert IssueRelation.create(:issue_from => independentIssue,
1964 :issue_to => childIssue2_1,
1976 :issue_to => childIssue2_1,
1965 :relation_type => IssueRelation::TYPE_RELATES)
1977 :relation_type => IssueRelation::TYPE_RELATES)
1966
1978
1967 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1979 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1968 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1980 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1969
1981
1970 end
1982 end
1971
1983
1972 def test_all_dependent_issues_with_persistent_circular_dependency
1984 def test_all_dependent_issues_with_persistent_circular_dependency
1973 IssueRelation.delete_all
1985 IssueRelation.delete_all
1974 assert IssueRelation.create!(:issue_from => Issue.find(1),
1986 assert IssueRelation.create!(:issue_from => Issue.find(1),
1975 :issue_to => Issue.find(2),
1987 :issue_to => Issue.find(2),
1976 :relation_type => IssueRelation::TYPE_PRECEDES)
1988 :relation_type => IssueRelation::TYPE_PRECEDES)
1977 assert IssueRelation.create!(:issue_from => Issue.find(2),
1989 assert IssueRelation.create!(:issue_from => Issue.find(2),
1978 :issue_to => Issue.find(3),
1990 :issue_to => Issue.find(3),
1979 :relation_type => IssueRelation::TYPE_PRECEDES)
1991 :relation_type => IssueRelation::TYPE_PRECEDES)
1980
1992
1981 r = IssueRelation.create!(:issue_from => Issue.find(3),
1993 r = IssueRelation.create!(:issue_from => Issue.find(3),
1982 :issue_to => Issue.find(7),
1994 :issue_to => Issue.find(7),
1983 :relation_type => IssueRelation::TYPE_PRECEDES)
1995 :relation_type => IssueRelation::TYPE_PRECEDES)
1984 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1996 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1985
1997
1986 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1998 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1987 end
1999 end
1988
2000
1989 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
2001 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1990 IssueRelation.delete_all
2002 IssueRelation.delete_all
1991 assert IssueRelation.create!(:issue_from => Issue.find(1),
2003 assert IssueRelation.create!(:issue_from => Issue.find(1),
1992 :issue_to => Issue.find(2),
2004 :issue_to => Issue.find(2),
1993 :relation_type => IssueRelation::TYPE_RELATES)
2005 :relation_type => IssueRelation::TYPE_RELATES)
1994 assert IssueRelation.create!(:issue_from => Issue.find(2),
2006 assert IssueRelation.create!(:issue_from => Issue.find(2),
1995 :issue_to => Issue.find(3),
2007 :issue_to => Issue.find(3),
1996 :relation_type => IssueRelation::TYPE_RELATES)
2008 :relation_type => IssueRelation::TYPE_RELATES)
1997 assert IssueRelation.create!(:issue_from => Issue.find(3),
2009 assert IssueRelation.create!(:issue_from => Issue.find(3),
1998 :issue_to => Issue.find(8),
2010 :issue_to => Issue.find(8),
1999 :relation_type => IssueRelation::TYPE_RELATES)
2011 :relation_type => IssueRelation::TYPE_RELATES)
2000
2012
2001 r = IssueRelation.create!(:issue_from => Issue.find(8),
2013 r = IssueRelation.create!(:issue_from => Issue.find(8),
2002 :issue_to => Issue.find(7),
2014 :issue_to => Issue.find(7),
2003 :relation_type => IssueRelation::TYPE_RELATES)
2015 :relation_type => IssueRelation::TYPE_RELATES)
2004 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
2016 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
2005
2017
2006 r = IssueRelation.create!(:issue_from => Issue.find(3),
2018 r = IssueRelation.create!(:issue_from => Issue.find(3),
2007 :issue_to => Issue.find(7),
2019 :issue_to => Issue.find(7),
2008 :relation_type => IssueRelation::TYPE_RELATES)
2020 :relation_type => IssueRelation::TYPE_RELATES)
2009 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
2021 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
2010
2022
2011 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2023 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2012 end
2024 end
2013
2025
2014 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
2026 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
2015 @issue = Issue.find(1)
2027 @issue = Issue.find(1)
2016 @issue_status = IssueStatus.find(1)
2028 @issue_status = IssueStatus.find(1)
2017 @issue_status.update_attribute(:default_done_ratio, 50)
2029 @issue_status.update_attribute(:default_done_ratio, 50)
2018 @issue2 = Issue.find(2)
2030 @issue2 = Issue.find(2)
2019 @issue_status2 = IssueStatus.find(2)
2031 @issue_status2 = IssueStatus.find(2)
2020 @issue_status2.update_attribute(:default_done_ratio, 0)
2032 @issue_status2.update_attribute(:default_done_ratio, 0)
2021
2033
2022 with_settings :issue_done_ratio => 'issue_field' do
2034 with_settings :issue_done_ratio => 'issue_field' do
2023 assert_equal 0, @issue.done_ratio
2035 assert_equal 0, @issue.done_ratio
2024 assert_equal 30, @issue2.done_ratio
2036 assert_equal 30, @issue2.done_ratio
2025 end
2037 end
2026
2038
2027 with_settings :issue_done_ratio => 'issue_status' do
2039 with_settings :issue_done_ratio => 'issue_status' do
2028 assert_equal 50, @issue.done_ratio
2040 assert_equal 50, @issue.done_ratio
2029 assert_equal 0, @issue2.done_ratio
2041 assert_equal 0, @issue2.done_ratio
2030 end
2042 end
2031 end
2043 end
2032
2044
2033 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2045 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2034 @issue = Issue.find(1)
2046 @issue = Issue.find(1)
2035 @issue_status = IssueStatus.find(1)
2047 @issue_status = IssueStatus.find(1)
2036 @issue_status.update_attribute(:default_done_ratio, 50)
2048 @issue_status.update_attribute(:default_done_ratio, 50)
2037 @issue2 = Issue.find(2)
2049 @issue2 = Issue.find(2)
2038 @issue_status2 = IssueStatus.find(2)
2050 @issue_status2 = IssueStatus.find(2)
2039 @issue_status2.update_attribute(:default_done_ratio, 0)
2051 @issue_status2.update_attribute(:default_done_ratio, 0)
2040
2052
2041 with_settings :issue_done_ratio => 'issue_field' do
2053 with_settings :issue_done_ratio => 'issue_field' do
2042 @issue.update_done_ratio_from_issue_status
2054 @issue.update_done_ratio_from_issue_status
2043 @issue2.update_done_ratio_from_issue_status
2055 @issue2.update_done_ratio_from_issue_status
2044
2056
2045 assert_equal 0, @issue.read_attribute(:done_ratio)
2057 assert_equal 0, @issue.read_attribute(:done_ratio)
2046 assert_equal 30, @issue2.read_attribute(:done_ratio)
2058 assert_equal 30, @issue2.read_attribute(:done_ratio)
2047 end
2059 end
2048
2060
2049 with_settings :issue_done_ratio => 'issue_status' do
2061 with_settings :issue_done_ratio => 'issue_status' do
2050 @issue.update_done_ratio_from_issue_status
2062 @issue.update_done_ratio_from_issue_status
2051 @issue2.update_done_ratio_from_issue_status
2063 @issue2.update_done_ratio_from_issue_status
2052
2064
2053 assert_equal 50, @issue.read_attribute(:done_ratio)
2065 assert_equal 50, @issue.read_attribute(:done_ratio)
2054 assert_equal 0, @issue2.read_attribute(:done_ratio)
2066 assert_equal 0, @issue2.read_attribute(:done_ratio)
2055 end
2067 end
2056 end
2068 end
2057
2069
2058 test "#by_tracker" do
2070 test "#by_tracker" do
2059 User.current = User.anonymous
2071 User.current = User.anonymous
2060 groups = Issue.by_tracker(Project.find(1))
2072 groups = Issue.by_tracker(Project.find(1))
2061 assert_equal 3, groups.count
2073 assert_equal 3, groups.count
2062 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2074 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2063 end
2075 end
2064
2076
2065 test "#by_version" do
2077 test "#by_version" do
2066 User.current = User.anonymous
2078 User.current = User.anonymous
2067 groups = Issue.by_version(Project.find(1))
2079 groups = Issue.by_version(Project.find(1))
2068 assert_equal 3, groups.count
2080 assert_equal 3, groups.count
2069 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2081 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2070 end
2082 end
2071
2083
2072 test "#by_priority" do
2084 test "#by_priority" do
2073 User.current = User.anonymous
2085 User.current = User.anonymous
2074 groups = Issue.by_priority(Project.find(1))
2086 groups = Issue.by_priority(Project.find(1))
2075 assert_equal 4, groups.count
2087 assert_equal 4, groups.count
2076 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2088 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2077 end
2089 end
2078
2090
2079 test "#by_category" do
2091 test "#by_category" do
2080 User.current = User.anonymous
2092 User.current = User.anonymous
2081 groups = Issue.by_category(Project.find(1))
2093 groups = Issue.by_category(Project.find(1))
2082 assert_equal 2, groups.count
2094 assert_equal 2, groups.count
2083 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2095 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2084 end
2096 end
2085
2097
2086 test "#by_assigned_to" do
2098 test "#by_assigned_to" do
2087 User.current = User.anonymous
2099 User.current = User.anonymous
2088 groups = Issue.by_assigned_to(Project.find(1))
2100 groups = Issue.by_assigned_to(Project.find(1))
2089 assert_equal 2, groups.count
2101 assert_equal 2, groups.count
2090 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2102 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2091 end
2103 end
2092
2104
2093 test "#by_author" do
2105 test "#by_author" do
2094 User.current = User.anonymous
2106 User.current = User.anonymous
2095 groups = Issue.by_author(Project.find(1))
2107 groups = Issue.by_author(Project.find(1))
2096 assert_equal 4, groups.count
2108 assert_equal 4, groups.count
2097 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2109 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2098 end
2110 end
2099
2111
2100 test "#by_subproject" do
2112 test "#by_subproject" do
2101 User.current = User.anonymous
2113 User.current = User.anonymous
2102 groups = Issue.by_subproject(Project.find(1))
2114 groups = Issue.by_subproject(Project.find(1))
2103 # Private descendant not visible
2115 # Private descendant not visible
2104 assert_equal 1, groups.count
2116 assert_equal 1, groups.count
2105 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2117 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2106 end
2118 end
2107
2119
2108 def test_recently_updated_scope
2120 def test_recently_updated_scope
2109 #should return the last updated issue
2121 #should return the last updated issue
2110 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2122 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2111 end
2123 end
2112
2124
2113 def test_on_active_projects_scope
2125 def test_on_active_projects_scope
2114 assert Project.find(2).archive
2126 assert Project.find(2).archive
2115
2127
2116 before = Issue.on_active_project.length
2128 before = Issue.on_active_project.length
2117 # test inclusion to results
2129 # test inclusion to results
2118 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2130 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2119 assert_equal before + 1, Issue.on_active_project.length
2131 assert_equal before + 1, Issue.on_active_project.length
2120
2132
2121 # Move to an archived project
2133 # Move to an archived project
2122 issue.project = Project.find(2)
2134 issue.project = Project.find(2)
2123 assert issue.save
2135 assert issue.save
2124 assert_equal before, Issue.on_active_project.length
2136 assert_equal before, Issue.on_active_project.length
2125 end
2137 end
2126
2138
2127 test "Issue#recipients should include project recipients" do
2139 test "Issue#recipients should include project recipients" do
2128 issue = Issue.generate!
2140 issue = Issue.generate!
2129 assert issue.project.recipients.present?
2141 assert issue.project.recipients.present?
2130 issue.project.recipients.each do |project_recipient|
2142 issue.project.recipients.each do |project_recipient|
2131 assert issue.recipients.include?(project_recipient)
2143 assert issue.recipients.include?(project_recipient)
2132 end
2144 end
2133 end
2145 end
2134
2146
2135 test "Issue#recipients should include the author if the author is active" do
2147 test "Issue#recipients should include the author if the author is active" do
2136 issue = Issue.generate!(:author => User.generate!)
2148 issue = Issue.generate!(:author => User.generate!)
2137 assert issue.author, "No author set for Issue"
2149 assert issue.author, "No author set for Issue"
2138 assert issue.recipients.include?(issue.author.mail)
2150 assert issue.recipients.include?(issue.author.mail)
2139 end
2151 end
2140
2152
2141 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2153 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2142 issue = Issue.generate!(:assigned_to => User.generate!)
2154 issue = Issue.generate!(:assigned_to => User.generate!)
2143 assert issue.assigned_to, "No assigned_to set for Issue"
2155 assert issue.assigned_to, "No assigned_to set for Issue"
2144 assert issue.recipients.include?(issue.assigned_to.mail)
2156 assert issue.recipients.include?(issue.assigned_to.mail)
2145 end
2157 end
2146
2158
2147 test "Issue#recipients should not include users who opt out of all email" do
2159 test "Issue#recipients should not include users who opt out of all email" do
2148 issue = Issue.generate!(:author => User.generate!)
2160 issue = Issue.generate!(:author => User.generate!)
2149 issue.author.update_attribute(:mail_notification, :none)
2161 issue.author.update_attribute(:mail_notification, :none)
2150 assert !issue.recipients.include?(issue.author.mail)
2162 assert !issue.recipients.include?(issue.author.mail)
2151 end
2163 end
2152
2164
2153 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2165 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2154 issue = Issue.generate!(:author => User.generate!)
2166 issue = Issue.generate!(:author => User.generate!)
2155 issue.author.update_attribute(:mail_notification, :only_assigned)
2167 issue.author.update_attribute(:mail_notification, :only_assigned)
2156 assert !issue.recipients.include?(issue.author.mail)
2168 assert !issue.recipients.include?(issue.author.mail)
2157 end
2169 end
2158
2170
2159 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2171 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2160 issue = Issue.generate!(:assigned_to => User.generate!)
2172 issue = Issue.generate!(:assigned_to => User.generate!)
2161 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2173 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2162 assert !issue.recipients.include?(issue.assigned_to.mail)
2174 assert !issue.recipients.include?(issue.assigned_to.mail)
2163 end
2175 end
2164
2176
2165 def test_last_journal_id_with_journals_should_return_the_journal_id
2177 def test_last_journal_id_with_journals_should_return_the_journal_id
2166 assert_equal 2, Issue.find(1).last_journal_id
2178 assert_equal 2, Issue.find(1).last_journal_id
2167 end
2179 end
2168
2180
2169 def test_last_journal_id_without_journals_should_return_nil
2181 def test_last_journal_id_without_journals_should_return_nil
2170 assert_nil Issue.find(3).last_journal_id
2182 assert_nil Issue.find(3).last_journal_id
2171 end
2183 end
2172
2184
2173 def test_journals_after_should_return_journals_with_greater_id
2185 def test_journals_after_should_return_journals_with_greater_id
2174 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2186 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2175 assert_equal [], Issue.find(1).journals_after('2')
2187 assert_equal [], Issue.find(1).journals_after('2')
2176 end
2188 end
2177
2189
2178 def test_journals_after_with_blank_arg_should_return_all_journals
2190 def test_journals_after_with_blank_arg_should_return_all_journals
2179 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2191 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2180 end
2192 end
2181
2193
2182 def test_css_classes_should_include_tracker
2194 def test_css_classes_should_include_tracker
2183 issue = Issue.new(:tracker => Tracker.find(2))
2195 issue = Issue.new(:tracker => Tracker.find(2))
2184 classes = issue.css_classes.split(' ')
2196 classes = issue.css_classes.split(' ')
2185 assert_include 'tracker-2', classes
2197 assert_include 'tracker-2', classes
2186 end
2198 end
2187
2199
2188 def test_css_classes_should_include_priority
2200 def test_css_classes_should_include_priority
2189 issue = Issue.new(:priority => IssuePriority.find(8))
2201 issue = Issue.new(:priority => IssuePriority.find(8))
2190 classes = issue.css_classes.split(' ')
2202 classes = issue.css_classes.split(' ')
2191 assert_include 'priority-8', classes
2203 assert_include 'priority-8', classes
2192 assert_include 'priority-highest', classes
2204 assert_include 'priority-highest', classes
2193 end
2205 end
2194
2206
2195 def test_css_classes_should_include_user_assignment
2207 def test_css_classes_should_include_user_assignment
2196 issue = Issue.generate(:assigned_to_id => 2)
2208 issue = Issue.generate(:assigned_to_id => 2)
2197 assert_include 'assigned-to-me', issue.css_classes(User.find(2))
2209 assert_include 'assigned-to-me', issue.css_classes(User.find(2))
2198 assert_not_include 'assigned-to-me', issue.css_classes(User.find(3))
2210 assert_not_include 'assigned-to-me', issue.css_classes(User.find(3))
2199 end
2211 end
2200
2212
2201 def test_css_classes_should_include_user_group_assignment
2213 def test_css_classes_should_include_user_group_assignment
2202 issue = Issue.generate(:assigned_to_id => 10)
2214 issue = Issue.generate(:assigned_to_id => 10)
2203 assert_include 'assigned-to-my-group', issue.css_classes(Group.find(10).users.first)
2215 assert_include 'assigned-to-my-group', issue.css_classes(Group.find(10).users.first)
2204 assert_not_include 'assigned-to-my-group', issue.css_classes(User.find(3))
2216 assert_not_include 'assigned-to-my-group', issue.css_classes(User.find(3))
2205 end
2217 end
2206
2218
2207 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2219 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2208 set_tmp_attachments_directory
2220 set_tmp_attachments_directory
2209 issue = Issue.generate!
2221 issue = Issue.generate!
2210 issue.save_attachments({
2222 issue.save_attachments({
2211 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2223 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2212 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2224 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2213 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2225 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2214 })
2226 })
2215 issue.attach_saved_attachments
2227 issue.attach_saved_attachments
2216
2228
2217 assert_equal 3, issue.reload.attachments.count
2229 assert_equal 3, issue.reload.attachments.count
2218 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2230 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2219 end
2231 end
2220
2232
2221 def test_closed_on_should_be_nil_when_creating_an_open_issue
2233 def test_closed_on_should_be_nil_when_creating_an_open_issue
2222 issue = Issue.generate!(:status_id => 1).reload
2234 issue = Issue.generate!(:status_id => 1).reload
2223 assert !issue.closed?
2235 assert !issue.closed?
2224 assert_nil issue.closed_on
2236 assert_nil issue.closed_on
2225 end
2237 end
2226
2238
2227 def test_closed_on_should_be_set_when_creating_a_closed_issue
2239 def test_closed_on_should_be_set_when_creating_a_closed_issue
2228 issue = Issue.generate!(:status_id => 5).reload
2240 issue = Issue.generate!(:status_id => 5).reload
2229 assert issue.closed?
2241 assert issue.closed?
2230 assert_not_nil issue.closed_on
2242 assert_not_nil issue.closed_on
2231 assert_equal issue.updated_on, issue.closed_on
2243 assert_equal issue.updated_on, issue.closed_on
2232 assert_equal issue.created_on, issue.closed_on
2244 assert_equal issue.created_on, issue.closed_on
2233 end
2245 end
2234
2246
2235 def test_closed_on_should_be_nil_when_updating_an_open_issue
2247 def test_closed_on_should_be_nil_when_updating_an_open_issue
2236 issue = Issue.find(1)
2248 issue = Issue.find(1)
2237 issue.subject = 'Not closed yet'
2249 issue.subject = 'Not closed yet'
2238 issue.save!
2250 issue.save!
2239 issue.reload
2251 issue.reload
2240 assert_nil issue.closed_on
2252 assert_nil issue.closed_on
2241 end
2253 end
2242
2254
2243 def test_closed_on_should_be_set_when_closing_an_open_issue
2255 def test_closed_on_should_be_set_when_closing_an_open_issue
2244 issue = Issue.find(1)
2256 issue = Issue.find(1)
2245 issue.subject = 'Now closed'
2257 issue.subject = 'Now closed'
2246 issue.status_id = 5
2258 issue.status_id = 5
2247 issue.save!
2259 issue.save!
2248 issue.reload
2260 issue.reload
2249 assert_not_nil issue.closed_on
2261 assert_not_nil issue.closed_on
2250 assert_equal issue.updated_on, issue.closed_on
2262 assert_equal issue.updated_on, issue.closed_on
2251 end
2263 end
2252
2264
2253 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2265 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2254 issue = Issue.open(false).first
2266 issue = Issue.open(false).first
2255 was_closed_on = issue.closed_on
2267 was_closed_on = issue.closed_on
2256 assert_not_nil was_closed_on
2268 assert_not_nil was_closed_on
2257 issue.subject = 'Updating a closed issue'
2269 issue.subject = 'Updating a closed issue'
2258 issue.save!
2270 issue.save!
2259 issue.reload
2271 issue.reload
2260 assert_equal was_closed_on, issue.closed_on
2272 assert_equal was_closed_on, issue.closed_on
2261 end
2273 end
2262
2274
2263 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2275 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2264 issue = Issue.open(false).first
2276 issue = Issue.open(false).first
2265 was_closed_on = issue.closed_on
2277 was_closed_on = issue.closed_on
2266 assert_not_nil was_closed_on
2278 assert_not_nil was_closed_on
2267 issue.subject = 'Reopening a closed issue'
2279 issue.subject = 'Reopening a closed issue'
2268 issue.status_id = 1
2280 issue.status_id = 1
2269 issue.save!
2281 issue.save!
2270 issue.reload
2282 issue.reload
2271 assert !issue.closed?
2283 assert !issue.closed?
2272 assert_equal was_closed_on, issue.closed_on
2284 assert_equal was_closed_on, issue.closed_on
2273 end
2285 end
2274
2286
2275 def test_status_was_should_return_nil_for_new_issue
2287 def test_status_was_should_return_nil_for_new_issue
2276 issue = Issue.new
2288 issue = Issue.new
2277 assert_nil issue.status_was
2289 assert_nil issue.status_was
2278 end
2290 end
2279
2291
2280 def test_status_was_should_return_status_before_change
2292 def test_status_was_should_return_status_before_change
2281 issue = Issue.find(1)
2293 issue = Issue.find(1)
2282 issue.status = IssueStatus.find(2)
2294 issue.status = IssueStatus.find(2)
2283 assert_equal IssueStatus.find(1), issue.status_was
2295 assert_equal IssueStatus.find(1), issue.status_was
2284 end
2296 end
2285
2297
2286 def test_status_was_should_be_reset_on_save
2298 def test_status_was_should_be_reset_on_save
2287 issue = Issue.find(1)
2299 issue = Issue.find(1)
2288 issue.status = IssueStatus.find(2)
2300 issue.status = IssueStatus.find(2)
2289 assert_equal IssueStatus.find(1), issue.status_was
2301 assert_equal IssueStatus.find(1), issue.status_was
2290 assert issue.save!
2302 assert issue.save!
2291 assert_equal IssueStatus.find(2), issue.status_was
2303 assert_equal IssueStatus.find(2), issue.status_was
2292 end
2304 end
2293 end
2305 end
General Comments 0
You need to be logged in to leave comments. Login now