##// END OF EJS Templates
gender neutral source comment at test/unit/issue_test.rb...
Toshi MARUYAMA -
r11762:b38de1f5e27b
parent child
Show More
@@ -1,2258 +1,2258
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 he 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 he 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_nil issue.errors[:tracker_id]
493 assert_not_nil 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, :old_status_id => 1,
512 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1,
513 :new_status_id => 4, :author => false,
513 :new_status_id => 4, :author => false,
514 :assignee => true)
514 :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 end
540 end
541
541
542 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
542 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
543 admin = User.find(1)
543 admin = User.find(1)
544 issue = Issue.find(1)
544 issue = Issue.find(1)
545 assert !admin.member_of?(issue.project)
545 assert !admin.member_of?(issue.project)
546 expected_statuses = [issue.status] +
546 expected_statuses = [issue.status] +
547 WorkflowTransition.find_all_by_old_status_id(
547 WorkflowTransition.find_all_by_old_status_id(
548 issue.status_id).map(&:new_status).uniq.sort
548 issue.status_id).map(&:new_status).uniq.sort
549 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
549 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
550 end
550 end
551
551
552 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
552 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
553 issue = Issue.find(1).copy
553 issue = Issue.find(1).copy
554 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
554 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
555
555
556 issue = Issue.find(2).copy
556 issue = Issue.find(2).copy
557 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
557 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
558 end
558 end
559
559
560 def test_safe_attributes_names_should_not_include_disabled_field
560 def test_safe_attributes_names_should_not_include_disabled_field
561 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
561 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
562
562
563 issue = Issue.new(:tracker => tracker)
563 issue = Issue.new(:tracker => tracker)
564 assert_include 'tracker_id', issue.safe_attribute_names
564 assert_include 'tracker_id', issue.safe_attribute_names
565 assert_include 'status_id', issue.safe_attribute_names
565 assert_include 'status_id', issue.safe_attribute_names
566 assert_include 'subject', issue.safe_attribute_names
566 assert_include 'subject', issue.safe_attribute_names
567 assert_include 'description', issue.safe_attribute_names
567 assert_include 'description', issue.safe_attribute_names
568 assert_include 'custom_field_values', issue.safe_attribute_names
568 assert_include 'custom_field_values', issue.safe_attribute_names
569 assert_include 'custom_fields', issue.safe_attribute_names
569 assert_include 'custom_fields', issue.safe_attribute_names
570 assert_include 'lock_version', issue.safe_attribute_names
570 assert_include 'lock_version', issue.safe_attribute_names
571
571
572 tracker.core_fields.each do |field|
572 tracker.core_fields.each do |field|
573 assert_include field, issue.safe_attribute_names
573 assert_include field, issue.safe_attribute_names
574 end
574 end
575
575
576 tracker.disabled_core_fields.each do |field|
576 tracker.disabled_core_fields.each do |field|
577 assert_not_include field, issue.safe_attribute_names
577 assert_not_include field, issue.safe_attribute_names
578 end
578 end
579 end
579 end
580
580
581 def test_safe_attributes_should_ignore_disabled_fields
581 def test_safe_attributes_should_ignore_disabled_fields
582 tracker = Tracker.find(1)
582 tracker = Tracker.find(1)
583 tracker.core_fields = %w(assigned_to_id due_date)
583 tracker.core_fields = %w(assigned_to_id due_date)
584 tracker.save!
584 tracker.save!
585
585
586 issue = Issue.new(:tracker => tracker)
586 issue = Issue.new(:tracker => tracker)
587 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
587 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
588 assert_nil issue.start_date
588 assert_nil issue.start_date
589 assert_equal Date.parse('2012-07-14'), issue.due_date
589 assert_equal Date.parse('2012-07-14'), issue.due_date
590 end
590 end
591
591
592 def test_safe_attributes_should_accept_target_tracker_enabled_fields
592 def test_safe_attributes_should_accept_target_tracker_enabled_fields
593 source = Tracker.find(1)
593 source = Tracker.find(1)
594 source.core_fields = []
594 source.core_fields = []
595 source.save!
595 source.save!
596 target = Tracker.find(2)
596 target = Tracker.find(2)
597 target.core_fields = %w(assigned_to_id due_date)
597 target.core_fields = %w(assigned_to_id due_date)
598 target.save!
598 target.save!
599
599
600 issue = Issue.new(:tracker => source)
600 issue = Issue.new(:tracker => source)
601 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
601 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
602 assert_equal target, issue.tracker
602 assert_equal target, issue.tracker
603 assert_equal Date.parse('2012-07-14'), issue.due_date
603 assert_equal Date.parse('2012-07-14'), issue.due_date
604 end
604 end
605
605
606 def test_safe_attributes_should_not_include_readonly_fields
606 def test_safe_attributes_should_not_include_readonly_fields
607 WorkflowPermission.delete_all
607 WorkflowPermission.delete_all
608 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
608 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
609 :role_id => 1, :field_name => 'due_date',
609 :role_id => 1, :field_name => 'due_date',
610 :rule => 'readonly')
610 :rule => 'readonly')
611 user = User.find(2)
611 user = User.find(2)
612
612
613 issue = Issue.new(:project_id => 1, :tracker_id => 1)
613 issue = Issue.new(:project_id => 1, :tracker_id => 1)
614 assert_equal %w(due_date), issue.read_only_attribute_names(user)
614 assert_equal %w(due_date), issue.read_only_attribute_names(user)
615 assert_not_include 'due_date', issue.safe_attribute_names(user)
615 assert_not_include 'due_date', issue.safe_attribute_names(user)
616
616
617 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
617 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
618 assert_equal Date.parse('2012-07-14'), issue.start_date
618 assert_equal Date.parse('2012-07-14'), issue.start_date
619 assert_nil issue.due_date
619 assert_nil issue.due_date
620 end
620 end
621
621
622 def test_safe_attributes_should_not_include_readonly_custom_fields
622 def test_safe_attributes_should_not_include_readonly_custom_fields
623 cf1 = IssueCustomField.create!(:name => 'Writable field',
623 cf1 = IssueCustomField.create!(:name => 'Writable field',
624 :field_format => 'string',
624 :field_format => 'string',
625 :is_for_all => true, :tracker_ids => [1])
625 :is_for_all => true, :tracker_ids => [1])
626 cf2 = IssueCustomField.create!(:name => 'Readonly field',
626 cf2 = IssueCustomField.create!(:name => 'Readonly field',
627 :field_format => 'string',
627 :field_format => 'string',
628 :is_for_all => true, :tracker_ids => [1])
628 :is_for_all => true, :tracker_ids => [1])
629 WorkflowPermission.delete_all
629 WorkflowPermission.delete_all
630 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
630 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
631 :role_id => 1, :field_name => cf2.id.to_s,
631 :role_id => 1, :field_name => cf2.id.to_s,
632 :rule => 'readonly')
632 :rule => 'readonly')
633 user = User.find(2)
633 user = User.find(2)
634 issue = Issue.new(:project_id => 1, :tracker_id => 1)
634 issue = Issue.new(:project_id => 1, :tracker_id => 1)
635 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
635 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
636 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
636 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
637
637
638 issue.send :safe_attributes=, {'custom_field_values' => {
638 issue.send :safe_attributes=, {'custom_field_values' => {
639 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
639 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
640 }}, user
640 }}, user
641 assert_equal 'value1', issue.custom_field_value(cf1)
641 assert_equal 'value1', issue.custom_field_value(cf1)
642 assert_nil issue.custom_field_value(cf2)
642 assert_nil issue.custom_field_value(cf2)
643
643
644 issue.send :safe_attributes=, {'custom_fields' => [
644 issue.send :safe_attributes=, {'custom_fields' => [
645 {'id' => cf1.id.to_s, 'value' => 'valuea'},
645 {'id' => cf1.id.to_s, 'value' => 'valuea'},
646 {'id' => cf2.id.to_s, 'value' => 'valueb'}
646 {'id' => cf2.id.to_s, 'value' => 'valueb'}
647 ]}, user
647 ]}, user
648 assert_equal 'valuea', issue.custom_field_value(cf1)
648 assert_equal 'valuea', issue.custom_field_value(cf1)
649 assert_nil issue.custom_field_value(cf2)
649 assert_nil issue.custom_field_value(cf2)
650 end
650 end
651
651
652 def test_editable_custom_field_values_should_return_non_readonly_custom_values
652 def test_editable_custom_field_values_should_return_non_readonly_custom_values
653 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
653 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
654 :is_for_all => true, :tracker_ids => [1, 2])
654 :is_for_all => true, :tracker_ids => [1, 2])
655 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
655 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
656 :is_for_all => true, :tracker_ids => [1, 2])
656 :is_for_all => true, :tracker_ids => [1, 2])
657 WorkflowPermission.delete_all
657 WorkflowPermission.delete_all
658 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
658 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
659 :field_name => cf2.id.to_s, :rule => 'readonly')
659 :field_name => cf2.id.to_s, :rule => 'readonly')
660 user = User.find(2)
660 user = User.find(2)
661
661
662 issue = Issue.new(:project_id => 1, :tracker_id => 1)
662 issue = Issue.new(:project_id => 1, :tracker_id => 1)
663 values = issue.editable_custom_field_values(user)
663 values = issue.editable_custom_field_values(user)
664 assert values.detect {|value| value.custom_field == cf1}
664 assert values.detect {|value| value.custom_field == cf1}
665 assert_nil values.detect {|value| value.custom_field == cf2}
665 assert_nil values.detect {|value| value.custom_field == cf2}
666
666
667 issue.tracker_id = 2
667 issue.tracker_id = 2
668 values = issue.editable_custom_field_values(user)
668 values = issue.editable_custom_field_values(user)
669 assert values.detect {|value| value.custom_field == cf1}
669 assert values.detect {|value| value.custom_field == cf1}
670 assert values.detect {|value| value.custom_field == cf2}
670 assert values.detect {|value| value.custom_field == cf2}
671 end
671 end
672
672
673 def test_safe_attributes_should_accept_target_tracker_writable_fields
673 def test_safe_attributes_should_accept_target_tracker_writable_fields
674 WorkflowPermission.delete_all
674 WorkflowPermission.delete_all
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
676 :role_id => 1, :field_name => 'due_date',
676 :role_id => 1, :field_name => 'due_date',
677 :rule => 'readonly')
677 :rule => 'readonly')
678 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
678 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
679 :role_id => 1, :field_name => 'start_date',
679 :role_id => 1, :field_name => 'start_date',
680 :rule => 'readonly')
680 :rule => 'readonly')
681 user = User.find(2)
681 user = User.find(2)
682
682
683 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
683 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
684
684
685 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
685 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
686 'due_date' => '2012-07-14'}, user
686 'due_date' => '2012-07-14'}, user
687 assert_equal Date.parse('2012-07-12'), issue.start_date
687 assert_equal Date.parse('2012-07-12'), issue.start_date
688 assert_nil issue.due_date
688 assert_nil issue.due_date
689
689
690 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
690 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
691 'due_date' => '2012-07-16',
691 'due_date' => '2012-07-16',
692 'tracker_id' => 2}, user
692 'tracker_id' => 2}, user
693 assert_equal Date.parse('2012-07-12'), issue.start_date
693 assert_equal Date.parse('2012-07-12'), issue.start_date
694 assert_equal Date.parse('2012-07-16'), issue.due_date
694 assert_equal Date.parse('2012-07-16'), issue.due_date
695 end
695 end
696
696
697 def test_safe_attributes_should_accept_target_status_writable_fields
697 def test_safe_attributes_should_accept_target_status_writable_fields
698 WorkflowPermission.delete_all
698 WorkflowPermission.delete_all
699 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
699 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
700 :role_id => 1, :field_name => 'due_date',
700 :role_id => 1, :field_name => 'due_date',
701 :rule => 'readonly')
701 :rule => 'readonly')
702 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
702 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
703 :role_id => 1, :field_name => 'start_date',
703 :role_id => 1, :field_name => 'start_date',
704 :rule => 'readonly')
704 :rule => 'readonly')
705 user = User.find(2)
705 user = User.find(2)
706
706
707 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
707 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
708
708
709 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
709 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
710 'due_date' => '2012-07-14'},
710 'due_date' => '2012-07-14'},
711 user
711 user
712 assert_equal Date.parse('2012-07-12'), issue.start_date
712 assert_equal Date.parse('2012-07-12'), issue.start_date
713 assert_nil issue.due_date
713 assert_nil issue.due_date
714
714
715 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
715 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
716 'due_date' => '2012-07-16',
716 'due_date' => '2012-07-16',
717 'status_id' => 2},
717 'status_id' => 2},
718 user
718 user
719 assert_equal Date.parse('2012-07-12'), issue.start_date
719 assert_equal Date.parse('2012-07-12'), issue.start_date
720 assert_equal Date.parse('2012-07-16'), issue.due_date
720 assert_equal Date.parse('2012-07-16'), issue.due_date
721 end
721 end
722
722
723 def test_required_attributes_should_be_validated
723 def test_required_attributes_should_be_validated
724 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
724 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
725 :is_for_all => true, :tracker_ids => [1, 2])
725 :is_for_all => true, :tracker_ids => [1, 2])
726
726
727 WorkflowPermission.delete_all
727 WorkflowPermission.delete_all
728 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
728 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
729 :role_id => 1, :field_name => 'due_date',
729 :role_id => 1, :field_name => 'due_date',
730 :rule => 'required')
730 :rule => 'required')
731 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
731 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
732 :role_id => 1, :field_name => 'category_id',
732 :role_id => 1, :field_name => 'category_id',
733 :rule => 'required')
733 :rule => 'required')
734 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
734 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
735 :role_id => 1, :field_name => cf.id.to_s,
735 :role_id => 1, :field_name => cf.id.to_s,
736 :rule => 'required')
736 :rule => 'required')
737
737
738 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
738 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
739 :role_id => 1, :field_name => 'start_date',
739 :role_id => 1, :field_name => 'start_date',
740 :rule => 'required')
740 :rule => 'required')
741 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
741 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
742 :role_id => 1, :field_name => cf.id.to_s,
742 :role_id => 1, :field_name => cf.id.to_s,
743 :rule => 'required')
743 :rule => 'required')
744 user = User.find(2)
744 user = User.find(2)
745
745
746 issue = Issue.new(:project_id => 1, :tracker_id => 1,
746 issue = Issue.new(:project_id => 1, :tracker_id => 1,
747 :status_id => 1, :subject => 'Required fields',
747 :status_id => 1, :subject => 'Required fields',
748 :author => user)
748 :author => user)
749 assert_equal [cf.id.to_s, "category_id", "due_date"],
749 assert_equal [cf.id.to_s, "category_id", "due_date"],
750 issue.required_attribute_names(user).sort
750 issue.required_attribute_names(user).sort
751 assert !issue.save, "Issue was saved"
751 assert !issue.save, "Issue was saved"
752 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
752 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
753 issue.errors.full_messages.sort
753 issue.errors.full_messages.sort
754
754
755 issue.tracker_id = 2
755 issue.tracker_id = 2
756 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
756 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
757 assert !issue.save, "Issue was saved"
757 assert !issue.save, "Issue was saved"
758 assert_equal ["Foo can't be blank", "Start date can't be blank"],
758 assert_equal ["Foo can't be blank", "Start date can't be blank"],
759 issue.errors.full_messages.sort
759 issue.errors.full_messages.sort
760
760
761 issue.start_date = Date.today
761 issue.start_date = Date.today
762 issue.custom_field_values = {cf.id.to_s => 'bar'}
762 issue.custom_field_values = {cf.id.to_s => 'bar'}
763 assert issue.save
763 assert issue.save
764 end
764 end
765
765
766 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
766 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
767 WorkflowPermission.delete_all
767 WorkflowPermission.delete_all
768 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
768 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
769 :role_id => 1, :field_name => 'due_date',
769 :role_id => 1, :field_name => 'due_date',
770 :rule => 'required')
770 :rule => 'required')
771 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
771 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
772 :role_id => 1, :field_name => 'start_date',
772 :role_id => 1, :field_name => 'start_date',
773 :rule => 'required')
773 :rule => 'required')
774 user = User.find(2)
774 user = User.find(2)
775 member = Member.find(1)
775 member = Member.find(1)
776 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
776 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
777
777
778 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
778 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
779
779
780 member.role_ids = [1, 2]
780 member.role_ids = [1, 2]
781 member.save!
781 member.save!
782 assert_equal [], issue.required_attribute_names(user.reload)
782 assert_equal [], issue.required_attribute_names(user.reload)
783
783
784 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
784 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
785 :role_id => 2, :field_name => 'due_date',
785 :role_id => 2, :field_name => 'due_date',
786 :rule => 'required')
786 :rule => 'required')
787 assert_equal %w(due_date), issue.required_attribute_names(user)
787 assert_equal %w(due_date), issue.required_attribute_names(user)
788
788
789 member.role_ids = [1, 2, 3]
789 member.role_ids = [1, 2, 3]
790 member.save!
790 member.save!
791 assert_equal [], issue.required_attribute_names(user.reload)
791 assert_equal [], issue.required_attribute_names(user.reload)
792
792
793 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
793 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
794 :role_id => 2, :field_name => 'due_date',
794 :role_id => 2, :field_name => 'due_date',
795 :rule => 'readonly')
795 :rule => 'readonly')
796 # required + readonly => required
796 # required + readonly => required
797 assert_equal %w(due_date), issue.required_attribute_names(user)
797 assert_equal %w(due_date), issue.required_attribute_names(user)
798 end
798 end
799
799
800 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
800 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
801 WorkflowPermission.delete_all
801 WorkflowPermission.delete_all
802 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
802 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
803 :role_id => 1, :field_name => 'due_date',
803 :role_id => 1, :field_name => 'due_date',
804 :rule => 'readonly')
804 :rule => 'readonly')
805 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
805 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
806 :role_id => 1, :field_name => 'start_date',
806 :role_id => 1, :field_name => 'start_date',
807 :rule => 'readonly')
807 :rule => 'readonly')
808 user = User.find(2)
808 user = User.find(2)
809 member = Member.find(1)
809 member = Member.find(1)
810 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
810 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
811
811
812 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
812 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
813
813
814 member.role_ids = [1, 2]
814 member.role_ids = [1, 2]
815 member.save!
815 member.save!
816 assert_equal [], issue.read_only_attribute_names(user.reload)
816 assert_equal [], issue.read_only_attribute_names(user.reload)
817
817
818 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
818 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
819 :role_id => 2, :field_name => 'due_date',
819 :role_id => 2, :field_name => 'due_date',
820 :rule => 'readonly')
820 :rule => 'readonly')
821 assert_equal %w(due_date), issue.read_only_attribute_names(user)
821 assert_equal %w(due_date), issue.read_only_attribute_names(user)
822 end
822 end
823
823
824 def test_copy
824 def test_copy
825 issue = Issue.new.copy_from(1)
825 issue = Issue.new.copy_from(1)
826 assert issue.copy?
826 assert issue.copy?
827 assert issue.save
827 assert issue.save
828 issue.reload
828 issue.reload
829 orig = Issue.find(1)
829 orig = Issue.find(1)
830 assert_equal orig.subject, issue.subject
830 assert_equal orig.subject, issue.subject
831 assert_equal orig.tracker, issue.tracker
831 assert_equal orig.tracker, issue.tracker
832 assert_equal "125", issue.custom_value_for(2).value
832 assert_equal "125", issue.custom_value_for(2).value
833 end
833 end
834
834
835 def test_copy_should_copy_status
835 def test_copy_should_copy_status
836 orig = Issue.find(8)
836 orig = Issue.find(8)
837 assert orig.status != IssueStatus.default
837 assert orig.status != IssueStatus.default
838
838
839 issue = Issue.new.copy_from(orig)
839 issue = Issue.new.copy_from(orig)
840 assert issue.save
840 assert issue.save
841 issue.reload
841 issue.reload
842 assert_equal orig.status, issue.status
842 assert_equal orig.status, issue.status
843 end
843 end
844
844
845 def test_copy_should_add_relation_with_copied_issue
845 def test_copy_should_add_relation_with_copied_issue
846 copied = Issue.find(1)
846 copied = Issue.find(1)
847 issue = Issue.new.copy_from(copied)
847 issue = Issue.new.copy_from(copied)
848 assert issue.save
848 assert issue.save
849 issue.reload
849 issue.reload
850
850
851 assert_equal 1, issue.relations.size
851 assert_equal 1, issue.relations.size
852 relation = issue.relations.first
852 relation = issue.relations.first
853 assert_equal 'copied_to', relation.relation_type
853 assert_equal 'copied_to', relation.relation_type
854 assert_equal copied, relation.issue_from
854 assert_equal copied, relation.issue_from
855 assert_equal issue, relation.issue_to
855 assert_equal issue, relation.issue_to
856 end
856 end
857
857
858 def test_copy_should_copy_subtasks
858 def test_copy_should_copy_subtasks
859 issue = Issue.generate_with_descendants!
859 issue = Issue.generate_with_descendants!
860
860
861 copy = issue.reload.copy
861 copy = issue.reload.copy
862 copy.author = User.find(7)
862 copy.author = User.find(7)
863 assert_difference 'Issue.count', 1+issue.descendants.count do
863 assert_difference 'Issue.count', 1+issue.descendants.count do
864 assert copy.save
864 assert copy.save
865 end
865 end
866 copy.reload
866 copy.reload
867 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
867 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
868 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
868 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
869 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
869 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
870 assert_equal copy.author, child_copy.author
870 assert_equal copy.author, child_copy.author
871 end
871 end
872
872
873 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
873 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
874 parent = Issue.generate!
874 parent = Issue.generate!
875 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
875 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
876 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
876 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
877
877
878 copy = parent.reload.copy
878 copy = parent.reload.copy
879 copy.parent_issue_id = parent.id
879 copy.parent_issue_id = parent.id
880 copy.author = User.find(7)
880 copy.author = User.find(7)
881 assert_difference 'Issue.count', 3 do
881 assert_difference 'Issue.count', 3 do
882 assert copy.save
882 assert copy.save
883 end
883 end
884 parent.reload
884 parent.reload
885 copy.reload
885 copy.reload
886 assert_equal parent, copy.parent
886 assert_equal parent, copy.parent
887 assert_equal 3, parent.children.count
887 assert_equal 3, parent.children.count
888 assert_equal 5, parent.descendants.count
888 assert_equal 5, parent.descendants.count
889 assert_equal 2, copy.children.count
889 assert_equal 2, copy.children.count
890 assert_equal 2, copy.descendants.count
890 assert_equal 2, copy.descendants.count
891 end
891 end
892
892
893 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
893 def test_copy_as_a_descendant_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 = child1.id
899 copy.parent_issue_id = child1.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 child1.reload
905 child1.reload
906 copy.reload
906 copy.reload
907 assert_equal child1, copy.parent
907 assert_equal child1, copy.parent
908 assert_equal 2, parent.children.count
908 assert_equal 2, parent.children.count
909 assert_equal 5, parent.descendants.count
909 assert_equal 5, parent.descendants.count
910 assert_equal 1, child1.children.count
910 assert_equal 1, child1.children.count
911 assert_equal 3, child1.descendants.count
911 assert_equal 3, child1.descendants.count
912 assert_equal 2, copy.children.count
912 assert_equal 2, copy.children.count
913 assert_equal 2, copy.descendants.count
913 assert_equal 2, copy.descendants.count
914 end
914 end
915
915
916 def test_copy_should_copy_subtasks_to_target_project
916 def test_copy_should_copy_subtasks_to_target_project
917 issue = Issue.generate_with_descendants!
917 issue = Issue.generate_with_descendants!
918
918
919 copy = issue.copy(:project_id => 3)
919 copy = issue.copy(:project_id => 3)
920 assert_difference 'Issue.count', 1+issue.descendants.count do
920 assert_difference 'Issue.count', 1+issue.descendants.count do
921 assert copy.save
921 assert copy.save
922 end
922 end
923 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
923 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
924 end
924 end
925
925
926 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
926 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
927 issue = Issue.generate_with_descendants!
927 issue = Issue.generate_with_descendants!
928
928
929 copy = issue.reload.copy
929 copy = issue.reload.copy
930 assert_difference 'Issue.count', 1+issue.descendants.count do
930 assert_difference 'Issue.count', 1+issue.descendants.count do
931 assert copy.save
931 assert copy.save
932 assert copy.save
932 assert copy.save
933 end
933 end
934 end
934 end
935
935
936 def test_should_not_call_after_project_change_on_creation
936 def test_should_not_call_after_project_change_on_creation
937 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
937 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
938 :subject => 'Test', :author_id => 1)
938 :subject => 'Test', :author_id => 1)
939 issue.expects(:after_project_change).never
939 issue.expects(:after_project_change).never
940 issue.save!
940 issue.save!
941 end
941 end
942
942
943 def test_should_not_call_after_project_change_on_update
943 def test_should_not_call_after_project_change_on_update
944 issue = Issue.find(1)
944 issue = Issue.find(1)
945 issue.project = Project.find(1)
945 issue.project = Project.find(1)
946 issue.subject = 'No project change'
946 issue.subject = 'No project change'
947 issue.expects(:after_project_change).never
947 issue.expects(:after_project_change).never
948 issue.save!
948 issue.save!
949 end
949 end
950
950
951 def test_should_call_after_project_change_on_project_change
951 def test_should_call_after_project_change_on_project_change
952 issue = Issue.find(1)
952 issue = Issue.find(1)
953 issue.project = Project.find(2)
953 issue.project = Project.find(2)
954 issue.expects(:after_project_change).once
954 issue.expects(:after_project_change).once
955 issue.save!
955 issue.save!
956 end
956 end
957
957
958 def test_adding_journal_should_update_timestamp
958 def test_adding_journal_should_update_timestamp
959 issue = Issue.find(1)
959 issue = Issue.find(1)
960 updated_on_was = issue.updated_on
960 updated_on_was = issue.updated_on
961
961
962 issue.init_journal(User.first, "Adding notes")
962 issue.init_journal(User.first, "Adding notes")
963 assert_difference 'Journal.count' do
963 assert_difference 'Journal.count' do
964 assert issue.save
964 assert issue.save
965 end
965 end
966 issue.reload
966 issue.reload
967
967
968 assert_not_equal updated_on_was, issue.updated_on
968 assert_not_equal updated_on_was, issue.updated_on
969 end
969 end
970
970
971 def test_should_close_duplicates
971 def test_should_close_duplicates
972 # Create 3 issues
972 # Create 3 issues
973 issue1 = Issue.generate!
973 issue1 = Issue.generate!
974 issue2 = Issue.generate!
974 issue2 = Issue.generate!
975 issue3 = Issue.generate!
975 issue3 = Issue.generate!
976
976
977 # 2 is a dupe of 1
977 # 2 is a dupe of 1
978 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
978 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
979 :relation_type => IssueRelation::TYPE_DUPLICATES)
979 :relation_type => IssueRelation::TYPE_DUPLICATES)
980 # And 3 is a dupe of 2
980 # And 3 is a dupe of 2
981 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
981 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
982 :relation_type => IssueRelation::TYPE_DUPLICATES)
982 :relation_type => IssueRelation::TYPE_DUPLICATES)
983 # And 3 is a dupe of 1 (circular duplicates)
983 # And 3 is a dupe of 1 (circular duplicates)
984 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
984 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
985 :relation_type => IssueRelation::TYPE_DUPLICATES)
985 :relation_type => IssueRelation::TYPE_DUPLICATES)
986
986
987 assert issue1.reload.duplicates.include?(issue2)
987 assert issue1.reload.duplicates.include?(issue2)
988
988
989 # Closing issue 1
989 # Closing issue 1
990 issue1.init_journal(User.first, "Closing issue1")
990 issue1.init_journal(User.first, "Closing issue1")
991 issue1.status = IssueStatus.where(:is_closed => true).first
991 issue1.status = IssueStatus.where(:is_closed => true).first
992 assert issue1.save
992 assert issue1.save
993 # 2 and 3 should be also closed
993 # 2 and 3 should be also closed
994 assert issue2.reload.closed?
994 assert issue2.reload.closed?
995 assert issue3.reload.closed?
995 assert issue3.reload.closed?
996 end
996 end
997
997
998 def test_should_not_close_duplicated_issue
998 def test_should_not_close_duplicated_issue
999 issue1 = Issue.generate!
999 issue1 = Issue.generate!
1000 issue2 = Issue.generate!
1000 issue2 = Issue.generate!
1001
1001
1002 # 2 is a dupe of 1
1002 # 2 is a dupe of 1
1003 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1003 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1004 :relation_type => IssueRelation::TYPE_DUPLICATES)
1004 :relation_type => IssueRelation::TYPE_DUPLICATES)
1005 # 2 is a dup of 1 but 1 is not a duplicate of 2
1005 # 2 is a dup of 1 but 1 is not a duplicate of 2
1006 assert !issue2.reload.duplicates.include?(issue1)
1006 assert !issue2.reload.duplicates.include?(issue1)
1007
1007
1008 # Closing issue 2
1008 # Closing issue 2
1009 issue2.init_journal(User.first, "Closing issue2")
1009 issue2.init_journal(User.first, "Closing issue2")
1010 issue2.status = IssueStatus.where(:is_closed => true).first
1010 issue2.status = IssueStatus.where(:is_closed => true).first
1011 assert issue2.save
1011 assert issue2.save
1012 # 1 should not be also closed
1012 # 1 should not be also closed
1013 assert !issue1.reload.closed?
1013 assert !issue1.reload.closed?
1014 end
1014 end
1015
1015
1016 def test_assignable_versions
1016 def test_assignable_versions
1017 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1017 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1018 :status_id => 1, :fixed_version_id => 1,
1018 :status_id => 1, :fixed_version_id => 1,
1019 :subject => 'New issue')
1019 :subject => 'New issue')
1020 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1020 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1021 end
1021 end
1022
1022
1023 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1023 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1024 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1024 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1025 :status_id => 1, :fixed_version_id => 1,
1025 :status_id => 1, :fixed_version_id => 1,
1026 :subject => 'New issue')
1026 :subject => 'New issue')
1027 assert !issue.save
1027 assert !issue.save
1028 assert_not_nil issue.errors[:fixed_version_id]
1028 assert_not_nil issue.errors[:fixed_version_id]
1029 end
1029 end
1030
1030
1031 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1031 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1032 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1032 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1033 :status_id => 1, :fixed_version_id => 2,
1033 :status_id => 1, :fixed_version_id => 2,
1034 :subject => 'New issue')
1034 :subject => 'New issue')
1035 assert !issue.save
1035 assert !issue.save
1036 assert_not_nil issue.errors[:fixed_version_id]
1036 assert_not_nil issue.errors[:fixed_version_id]
1037 end
1037 end
1038
1038
1039 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1039 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1040 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1040 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1041 :status_id => 1, :fixed_version_id => 3,
1041 :status_id => 1, :fixed_version_id => 3,
1042 :subject => 'New issue')
1042 :subject => 'New issue')
1043 assert issue.save
1043 assert issue.save
1044 end
1044 end
1045
1045
1046 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1046 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1047 issue = Issue.find(11)
1047 issue = Issue.find(11)
1048 assert_equal 'closed', issue.fixed_version.status
1048 assert_equal 'closed', issue.fixed_version.status
1049 issue.subject = 'Subject changed'
1049 issue.subject = 'Subject changed'
1050 assert issue.save
1050 assert issue.save
1051 end
1051 end
1052
1052
1053 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1053 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1054 issue = Issue.find(11)
1054 issue = Issue.find(11)
1055 issue.status_id = 1
1055 issue.status_id = 1
1056 assert !issue.save
1056 assert !issue.save
1057 assert_not_nil issue.errors[:base]
1057 assert_not_nil issue.errors[:base]
1058 end
1058 end
1059
1059
1060 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1060 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1061 issue = Issue.find(11)
1061 issue = Issue.find(11)
1062 issue.status_id = 1
1062 issue.status_id = 1
1063 issue.fixed_version_id = 3
1063 issue.fixed_version_id = 3
1064 assert issue.save
1064 assert issue.save
1065 end
1065 end
1066
1066
1067 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1067 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1068 issue = Issue.find(12)
1068 issue = Issue.find(12)
1069 assert_equal 'locked', issue.fixed_version.status
1069 assert_equal 'locked', issue.fixed_version.status
1070 issue.status_id = 1
1070 issue.status_id = 1
1071 assert issue.save
1071 assert issue.save
1072 end
1072 end
1073
1073
1074 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1074 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1075 issue = Issue.find(2)
1075 issue = Issue.find(2)
1076 assert_equal 2, issue.fixed_version_id
1076 assert_equal 2, issue.fixed_version_id
1077 issue.project_id = 3
1077 issue.project_id = 3
1078 assert_nil issue.fixed_version_id
1078 assert_nil issue.fixed_version_id
1079 issue.fixed_version_id = 2
1079 issue.fixed_version_id = 2
1080 assert !issue.save
1080 assert !issue.save
1081 assert_include 'Target version is not included in the list', issue.errors.full_messages
1081 assert_include 'Target version is not included in the list', issue.errors.full_messages
1082 end
1082 end
1083
1083
1084 def test_should_keep_shared_version_when_changing_project
1084 def test_should_keep_shared_version_when_changing_project
1085 Version.find(2).update_attribute :sharing, 'tree'
1085 Version.find(2).update_attribute :sharing, 'tree'
1086
1086
1087 issue = Issue.find(2)
1087 issue = Issue.find(2)
1088 assert_equal 2, issue.fixed_version_id
1088 assert_equal 2, issue.fixed_version_id
1089 issue.project_id = 3
1089 issue.project_id = 3
1090 assert_equal 2, issue.fixed_version_id
1090 assert_equal 2, issue.fixed_version_id
1091 assert issue.save
1091 assert issue.save
1092 end
1092 end
1093
1093
1094 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
1094 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
1095 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1095 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1096 end
1096 end
1097
1097
1098 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
1098 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
1099 Project.find(2).disable_module! :issue_tracking
1099 Project.find(2).disable_module! :issue_tracking
1100 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1100 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1101 end
1101 end
1102
1102
1103 def test_move_to_another_project_with_same_category
1103 def test_move_to_another_project_with_same_category
1104 issue = Issue.find(1)
1104 issue = Issue.find(1)
1105 issue.project = Project.find(2)
1105 issue.project = Project.find(2)
1106 assert issue.save
1106 assert issue.save
1107 issue.reload
1107 issue.reload
1108 assert_equal 2, issue.project_id
1108 assert_equal 2, issue.project_id
1109 # Category changes
1109 # Category changes
1110 assert_equal 4, issue.category_id
1110 assert_equal 4, issue.category_id
1111 # Make sure time entries were move to the target project
1111 # Make sure time entries were move to the target project
1112 assert_equal 2, issue.time_entries.first.project_id
1112 assert_equal 2, issue.time_entries.first.project_id
1113 end
1113 end
1114
1114
1115 def test_move_to_another_project_without_same_category
1115 def test_move_to_another_project_without_same_category
1116 issue = Issue.find(2)
1116 issue = Issue.find(2)
1117 issue.project = Project.find(2)
1117 issue.project = Project.find(2)
1118 assert issue.save
1118 assert issue.save
1119 issue.reload
1119 issue.reload
1120 assert_equal 2, issue.project_id
1120 assert_equal 2, issue.project_id
1121 # Category cleared
1121 # Category cleared
1122 assert_nil issue.category_id
1122 assert_nil issue.category_id
1123 end
1123 end
1124
1124
1125 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1125 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1126 issue = Issue.find(1)
1126 issue = Issue.find(1)
1127 issue.update_attribute(:fixed_version_id, 1)
1127 issue.update_attribute(:fixed_version_id, 1)
1128 issue.project = Project.find(2)
1128 issue.project = Project.find(2)
1129 assert issue.save
1129 assert issue.save
1130 issue.reload
1130 issue.reload
1131 assert_equal 2, issue.project_id
1131 assert_equal 2, issue.project_id
1132 # Cleared fixed_version
1132 # Cleared fixed_version
1133 assert_equal nil, issue.fixed_version
1133 assert_equal nil, issue.fixed_version
1134 end
1134 end
1135
1135
1136 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1136 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1137 issue = Issue.find(1)
1137 issue = Issue.find(1)
1138 issue.update_attribute(:fixed_version_id, 4)
1138 issue.update_attribute(:fixed_version_id, 4)
1139 issue.project = Project.find(5)
1139 issue.project = Project.find(5)
1140 assert issue.save
1140 assert issue.save
1141 issue.reload
1141 issue.reload
1142 assert_equal 5, issue.project_id
1142 assert_equal 5, issue.project_id
1143 # Keep fixed_version
1143 # Keep fixed_version
1144 assert_equal 4, issue.fixed_version_id
1144 assert_equal 4, issue.fixed_version_id
1145 end
1145 end
1146
1146
1147 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1147 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1148 issue = Issue.find(1)
1148 issue = Issue.find(1)
1149 issue.update_attribute(:fixed_version_id, 1)
1149 issue.update_attribute(:fixed_version_id, 1)
1150 issue.project = Project.find(5)
1150 issue.project = Project.find(5)
1151 assert issue.save
1151 assert issue.save
1152 issue.reload
1152 issue.reload
1153 assert_equal 5, issue.project_id
1153 assert_equal 5, issue.project_id
1154 # Cleared fixed_version
1154 # Cleared fixed_version
1155 assert_equal nil, issue.fixed_version
1155 assert_equal nil, issue.fixed_version
1156 end
1156 end
1157
1157
1158 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1158 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1159 issue = Issue.find(1)
1159 issue = Issue.find(1)
1160 issue.update_attribute(:fixed_version_id, 7)
1160 issue.update_attribute(:fixed_version_id, 7)
1161 issue.project = Project.find(2)
1161 issue.project = Project.find(2)
1162 assert issue.save
1162 assert issue.save
1163 issue.reload
1163 issue.reload
1164 assert_equal 2, issue.project_id
1164 assert_equal 2, issue.project_id
1165 # Keep fixed_version
1165 # Keep fixed_version
1166 assert_equal 7, issue.fixed_version_id
1166 assert_equal 7, issue.fixed_version_id
1167 end
1167 end
1168
1168
1169 def test_move_to_another_project_should_keep_parent_if_valid
1169 def test_move_to_another_project_should_keep_parent_if_valid
1170 issue = Issue.find(1)
1170 issue = Issue.find(1)
1171 issue.update_attribute(:parent_issue_id, 2)
1171 issue.update_attribute(:parent_issue_id, 2)
1172 issue.project = Project.find(3)
1172 issue.project = Project.find(3)
1173 assert issue.save
1173 assert issue.save
1174 issue.reload
1174 issue.reload
1175 assert_equal 2, issue.parent_id
1175 assert_equal 2, issue.parent_id
1176 end
1176 end
1177
1177
1178 def test_move_to_another_project_should_clear_parent_if_not_valid
1178 def test_move_to_another_project_should_clear_parent_if_not_valid
1179 issue = Issue.find(1)
1179 issue = Issue.find(1)
1180 issue.update_attribute(:parent_issue_id, 2)
1180 issue.update_attribute(:parent_issue_id, 2)
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_nil issue.parent_id
1184 assert_nil issue.parent_id
1185 end
1185 end
1186
1186
1187 def test_move_to_another_project_with_disabled_tracker
1187 def test_move_to_another_project_with_disabled_tracker
1188 issue = Issue.find(1)
1188 issue = Issue.find(1)
1189 target = Project.find(2)
1189 target = Project.find(2)
1190 target.tracker_ids = [3]
1190 target.tracker_ids = [3]
1191 target.save
1191 target.save
1192 issue.project = target
1192 issue.project = target
1193 assert issue.save
1193 assert issue.save
1194 issue.reload
1194 issue.reload
1195 assert_equal 2, issue.project_id
1195 assert_equal 2, issue.project_id
1196 assert_equal 3, issue.tracker_id
1196 assert_equal 3, issue.tracker_id
1197 end
1197 end
1198
1198
1199 def test_copy_to_the_same_project
1199 def test_copy_to_the_same_project
1200 issue = Issue.find(1)
1200 issue = Issue.find(1)
1201 copy = issue.copy
1201 copy = issue.copy
1202 assert_difference 'Issue.count' do
1202 assert_difference 'Issue.count' do
1203 copy.save!
1203 copy.save!
1204 end
1204 end
1205 assert_kind_of Issue, copy
1205 assert_kind_of Issue, copy
1206 assert_equal issue.project, copy.project
1206 assert_equal issue.project, copy.project
1207 assert_equal "125", copy.custom_value_for(2).value
1207 assert_equal "125", copy.custom_value_for(2).value
1208 end
1208 end
1209
1209
1210 def test_copy_to_another_project_and_tracker
1210 def test_copy_to_another_project_and_tracker
1211 issue = Issue.find(1)
1211 issue = Issue.find(1)
1212 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1212 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1213 assert_difference 'Issue.count' do
1213 assert_difference 'Issue.count' do
1214 copy.save!
1214 copy.save!
1215 end
1215 end
1216 copy.reload
1216 copy.reload
1217 assert_kind_of Issue, copy
1217 assert_kind_of Issue, copy
1218 assert_equal Project.find(3), copy.project
1218 assert_equal Project.find(3), copy.project
1219 assert_equal Tracker.find(2), copy.tracker
1219 assert_equal Tracker.find(2), copy.tracker
1220 # Custom field #2 is not associated with target tracker
1220 # Custom field #2 is not associated with target tracker
1221 assert_nil copy.custom_value_for(2)
1221 assert_nil copy.custom_value_for(2)
1222 end
1222 end
1223
1223
1224 test "#copy should not create a journal" do
1224 test "#copy should not create a journal" do
1225 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1225 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1226 copy.save!
1226 copy.save!
1227 assert_equal 0, copy.reload.journals.size
1227 assert_equal 0, copy.reload.journals.size
1228 end
1228 end
1229
1229
1230 test "#copy should allow assigned_to changes" do
1230 test "#copy should allow assigned_to changes" do
1231 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1231 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1232 assert_equal 3, copy.assigned_to_id
1232 assert_equal 3, copy.assigned_to_id
1233 end
1233 end
1234
1234
1235 test "#copy should allow status changes" do
1235 test "#copy should allow status changes" do
1236 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1236 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1237 assert_equal 2, copy.status_id
1237 assert_equal 2, copy.status_id
1238 end
1238 end
1239
1239
1240 test "#copy should allow start date changes" do
1240 test "#copy should allow start date changes" do
1241 date = Date.today
1241 date = Date.today
1242 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1242 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1243 assert_equal date, copy.start_date
1243 assert_equal date, copy.start_date
1244 end
1244 end
1245
1245
1246 test "#copy should allow due date changes" do
1246 test "#copy should allow due date changes" do
1247 date = Date.today
1247 date = Date.today
1248 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1248 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1249 assert_equal date, copy.due_date
1249 assert_equal date, copy.due_date
1250 end
1250 end
1251
1251
1252 test "#copy should set current user as author" do
1252 test "#copy should set current user as author" do
1253 User.current = User.find(9)
1253 User.current = User.find(9)
1254 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1254 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1255 assert_equal User.current, copy.author
1255 assert_equal User.current, copy.author
1256 end
1256 end
1257
1257
1258 test "#copy should create a journal with notes" do
1258 test "#copy should create a journal with notes" do
1259 date = Date.today
1259 date = Date.today
1260 notes = "Notes added when copying"
1260 notes = "Notes added when copying"
1261 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1261 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1262 copy.init_journal(User.current, notes)
1262 copy.init_journal(User.current, notes)
1263 copy.save!
1263 copy.save!
1264
1264
1265 assert_equal 1, copy.journals.size
1265 assert_equal 1, copy.journals.size
1266 journal = copy.journals.first
1266 journal = copy.journals.first
1267 assert_equal 0, journal.details.size
1267 assert_equal 0, journal.details.size
1268 assert_equal notes, journal.notes
1268 assert_equal notes, journal.notes
1269 end
1269 end
1270
1270
1271 def test_valid_parent_project
1271 def test_valid_parent_project
1272 issue = Issue.find(1)
1272 issue = Issue.find(1)
1273 issue_in_same_project = Issue.find(2)
1273 issue_in_same_project = Issue.find(2)
1274 issue_in_child_project = Issue.find(5)
1274 issue_in_child_project = Issue.find(5)
1275 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1275 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1276 issue_in_other_child_project = Issue.find(6)
1276 issue_in_other_child_project = Issue.find(6)
1277 issue_in_different_tree = Issue.find(4)
1277 issue_in_different_tree = Issue.find(4)
1278
1278
1279 with_settings :cross_project_subtasks => '' do
1279 with_settings :cross_project_subtasks => '' do
1280 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1280 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1281 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1281 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1282 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1282 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1283 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1283 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1284 end
1284 end
1285
1285
1286 with_settings :cross_project_subtasks => 'system' do
1286 with_settings :cross_project_subtasks => 'system' do
1287 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1287 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1288 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1288 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1289 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1289 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1290 end
1290 end
1291
1291
1292 with_settings :cross_project_subtasks => 'tree' do
1292 with_settings :cross_project_subtasks => 'tree' do
1293 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1293 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1294 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1294 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1295 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1295 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1296 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1296 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1297
1297
1298 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1298 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1299 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1299 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1300 end
1300 end
1301
1301
1302 with_settings :cross_project_subtasks => 'descendants' do
1302 with_settings :cross_project_subtasks => 'descendants' do
1303 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1303 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1304 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1304 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1305 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1305 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1306 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1306 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1307
1307
1308 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1308 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1309 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1309 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1310 end
1310 end
1311 end
1311 end
1312
1312
1313 def test_recipients_should_include_previous_assignee
1313 def test_recipients_should_include_previous_assignee
1314 user = User.find(3)
1314 user = User.find(3)
1315 user.members.update_all ["mail_notification = ?", false]
1315 user.members.update_all ["mail_notification = ?", false]
1316 user.update_attribute :mail_notification, 'only_assigned'
1316 user.update_attribute :mail_notification, 'only_assigned'
1317
1317
1318 issue = Issue.find(2)
1318 issue = Issue.find(2)
1319 issue.assigned_to = nil
1319 issue.assigned_to = nil
1320 assert_include user.mail, issue.recipients
1320 assert_include user.mail, issue.recipients
1321 issue.save!
1321 issue.save!
1322 assert !issue.recipients.include?(user.mail)
1322 assert !issue.recipients.include?(user.mail)
1323 end
1323 end
1324
1324
1325 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1325 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1326 issue = Issue.find(12)
1326 issue = Issue.find(12)
1327 assert issue.recipients.include?(issue.author.mail)
1327 assert issue.recipients.include?(issue.author.mail)
1328 # copy the issue to a private project
1328 # copy the issue to a private project
1329 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1329 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1330 # author is not a member of project anymore
1330 # author is not a member of project anymore
1331 assert !copy.recipients.include?(copy.author.mail)
1331 assert !copy.recipients.include?(copy.author.mail)
1332 end
1332 end
1333
1333
1334 def test_recipients_should_include_the_assigned_group_members
1334 def test_recipients_should_include_the_assigned_group_members
1335 group_member = User.generate!
1335 group_member = User.generate!
1336 group = Group.generate!
1336 group = Group.generate!
1337 group.users << group_member
1337 group.users << group_member
1338
1338
1339 issue = Issue.find(12)
1339 issue = Issue.find(12)
1340 issue.assigned_to = group
1340 issue.assigned_to = group
1341 assert issue.recipients.include?(group_member.mail)
1341 assert issue.recipients.include?(group_member.mail)
1342 end
1342 end
1343
1343
1344 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1344 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1345 user = User.find(3)
1345 user = User.find(3)
1346 issue = Issue.find(9)
1346 issue = Issue.find(9)
1347 Watcher.create!(:user => user, :watchable => issue)
1347 Watcher.create!(:user => user, :watchable => issue)
1348 assert issue.watched_by?(user)
1348 assert issue.watched_by?(user)
1349 assert !issue.watcher_recipients.include?(user.mail)
1349 assert !issue.watcher_recipients.include?(user.mail)
1350 end
1350 end
1351
1351
1352 def test_issue_destroy
1352 def test_issue_destroy
1353 Issue.find(1).destroy
1353 Issue.find(1).destroy
1354 assert_nil Issue.find_by_id(1)
1354 assert_nil Issue.find_by_id(1)
1355 assert_nil TimeEntry.find_by_issue_id(1)
1355 assert_nil TimeEntry.find_by_issue_id(1)
1356 end
1356 end
1357
1357
1358 def test_destroying_a_deleted_issue_should_not_raise_an_error
1358 def test_destroying_a_deleted_issue_should_not_raise_an_error
1359 issue = Issue.find(1)
1359 issue = Issue.find(1)
1360 Issue.find(1).destroy
1360 Issue.find(1).destroy
1361
1361
1362 assert_nothing_raised do
1362 assert_nothing_raised do
1363 assert_no_difference 'Issue.count' do
1363 assert_no_difference 'Issue.count' do
1364 issue.destroy
1364 issue.destroy
1365 end
1365 end
1366 assert issue.destroyed?
1366 assert issue.destroyed?
1367 end
1367 end
1368 end
1368 end
1369
1369
1370 def test_destroying_a_stale_issue_should_not_raise_an_error
1370 def test_destroying_a_stale_issue_should_not_raise_an_error
1371 issue = Issue.find(1)
1371 issue = Issue.find(1)
1372 Issue.find(1).update_attribute :subject, "Updated"
1372 Issue.find(1).update_attribute :subject, "Updated"
1373
1373
1374 assert_nothing_raised do
1374 assert_nothing_raised do
1375 assert_difference 'Issue.count', -1 do
1375 assert_difference 'Issue.count', -1 do
1376 issue.destroy
1376 issue.destroy
1377 end
1377 end
1378 assert issue.destroyed?
1378 assert issue.destroyed?
1379 end
1379 end
1380 end
1380 end
1381
1381
1382 def test_blocked
1382 def test_blocked
1383 blocked_issue = Issue.find(9)
1383 blocked_issue = Issue.find(9)
1384 blocking_issue = Issue.find(10)
1384 blocking_issue = Issue.find(10)
1385
1385
1386 assert blocked_issue.blocked?
1386 assert blocked_issue.blocked?
1387 assert !blocking_issue.blocked?
1387 assert !blocking_issue.blocked?
1388 end
1388 end
1389
1389
1390 def test_blocked_issues_dont_allow_closed_statuses
1390 def test_blocked_issues_dont_allow_closed_statuses
1391 blocked_issue = Issue.find(9)
1391 blocked_issue = Issue.find(9)
1392
1392
1393 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1393 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1394 assert !allowed_statuses.empty?
1394 assert !allowed_statuses.empty?
1395 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1395 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1396 assert closed_statuses.empty?
1396 assert closed_statuses.empty?
1397 end
1397 end
1398
1398
1399 def test_unblocked_issues_allow_closed_statuses
1399 def test_unblocked_issues_allow_closed_statuses
1400 blocking_issue = Issue.find(10)
1400 blocking_issue = Issue.find(10)
1401
1401
1402 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1402 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1403 assert !allowed_statuses.empty?
1403 assert !allowed_statuses.empty?
1404 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1404 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1405 assert !closed_statuses.empty?
1405 assert !closed_statuses.empty?
1406 end
1406 end
1407
1407
1408 def test_reschedule_an_issue_without_dates
1408 def test_reschedule_an_issue_without_dates
1409 with_settings :non_working_week_days => [] do
1409 with_settings :non_working_week_days => [] do
1410 issue = Issue.new(:start_date => nil, :due_date => nil)
1410 issue = Issue.new(:start_date => nil, :due_date => nil)
1411 issue.reschedule_on '2012-10-09'.to_date
1411 issue.reschedule_on '2012-10-09'.to_date
1412 assert_equal '2012-10-09'.to_date, issue.start_date
1412 assert_equal '2012-10-09'.to_date, issue.start_date
1413 assert_equal '2012-10-09'.to_date, issue.due_date
1413 assert_equal '2012-10-09'.to_date, issue.due_date
1414 end
1414 end
1415
1415
1416 with_settings :non_working_week_days => %w(6 7) do
1416 with_settings :non_working_week_days => %w(6 7) do
1417 issue = Issue.new(:start_date => nil, :due_date => nil)
1417 issue = Issue.new(:start_date => nil, :due_date => nil)
1418 issue.reschedule_on '2012-10-09'.to_date
1418 issue.reschedule_on '2012-10-09'.to_date
1419 assert_equal '2012-10-09'.to_date, issue.start_date
1419 assert_equal '2012-10-09'.to_date, issue.start_date
1420 assert_equal '2012-10-09'.to_date, issue.due_date
1420 assert_equal '2012-10-09'.to_date, issue.due_date
1421
1421
1422 issue = Issue.new(:start_date => nil, :due_date => nil)
1422 issue = Issue.new(:start_date => nil, :due_date => nil)
1423 issue.reschedule_on '2012-10-13'.to_date
1423 issue.reschedule_on '2012-10-13'.to_date
1424 assert_equal '2012-10-15'.to_date, issue.start_date
1424 assert_equal '2012-10-15'.to_date, issue.start_date
1425 assert_equal '2012-10-15'.to_date, issue.due_date
1425 assert_equal '2012-10-15'.to_date, issue.due_date
1426 end
1426 end
1427 end
1427 end
1428
1428
1429 def test_reschedule_an_issue_with_start_date
1429 def test_reschedule_an_issue_with_start_date
1430 with_settings :non_working_week_days => [] do
1430 with_settings :non_working_week_days => [] do
1431 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1431 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1432 issue.reschedule_on '2012-10-13'.to_date
1432 issue.reschedule_on '2012-10-13'.to_date
1433 assert_equal '2012-10-13'.to_date, issue.start_date
1433 assert_equal '2012-10-13'.to_date, issue.start_date
1434 assert_equal '2012-10-13'.to_date, issue.due_date
1434 assert_equal '2012-10-13'.to_date, issue.due_date
1435 end
1435 end
1436
1436
1437 with_settings :non_working_week_days => %w(6 7) do
1437 with_settings :non_working_week_days => %w(6 7) do
1438 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1438 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1439 issue.reschedule_on '2012-10-11'.to_date
1439 issue.reschedule_on '2012-10-11'.to_date
1440 assert_equal '2012-10-11'.to_date, issue.start_date
1440 assert_equal '2012-10-11'.to_date, issue.start_date
1441 assert_equal '2012-10-11'.to_date, issue.due_date
1441 assert_equal '2012-10-11'.to_date, issue.due_date
1442
1442
1443 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1443 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1444 issue.reschedule_on '2012-10-13'.to_date
1444 issue.reschedule_on '2012-10-13'.to_date
1445 assert_equal '2012-10-15'.to_date, issue.start_date
1445 assert_equal '2012-10-15'.to_date, issue.start_date
1446 assert_equal '2012-10-15'.to_date, issue.due_date
1446 assert_equal '2012-10-15'.to_date, issue.due_date
1447 end
1447 end
1448 end
1448 end
1449
1449
1450 def test_reschedule_an_issue_with_start_and_due_dates
1450 def test_reschedule_an_issue_with_start_and_due_dates
1451 with_settings :non_working_week_days => [] do
1451 with_settings :non_working_week_days => [] do
1452 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1452 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1453 issue.reschedule_on '2012-10-13'.to_date
1453 issue.reschedule_on '2012-10-13'.to_date
1454 assert_equal '2012-10-13'.to_date, issue.start_date
1454 assert_equal '2012-10-13'.to_date, issue.start_date
1455 assert_equal '2012-10-19'.to_date, issue.due_date
1455 assert_equal '2012-10-19'.to_date, issue.due_date
1456 end
1456 end
1457
1457
1458 with_settings :non_working_week_days => %w(6 7) do
1458 with_settings :non_working_week_days => %w(6 7) do
1459 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1459 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1460 issue.reschedule_on '2012-10-11'.to_date
1460 issue.reschedule_on '2012-10-11'.to_date
1461 assert_equal '2012-10-11'.to_date, issue.start_date
1461 assert_equal '2012-10-11'.to_date, issue.start_date
1462 assert_equal '2012-10-23'.to_date, issue.due_date
1462 assert_equal '2012-10-23'.to_date, issue.due_date
1463
1463
1464 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1464 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1465 issue.reschedule_on '2012-10-13'.to_date
1465 issue.reschedule_on '2012-10-13'.to_date
1466 assert_equal '2012-10-15'.to_date, issue.start_date
1466 assert_equal '2012-10-15'.to_date, issue.start_date
1467 assert_equal '2012-10-25'.to_date, issue.due_date
1467 assert_equal '2012-10-25'.to_date, issue.due_date
1468 end
1468 end
1469 end
1469 end
1470
1470
1471 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1471 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1472 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1472 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1473 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1473 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1474 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1474 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1475 :relation_type => IssueRelation::TYPE_PRECEDES)
1475 :relation_type => IssueRelation::TYPE_PRECEDES)
1476 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1476 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1477
1477
1478 issue1.reload
1478 issue1.reload
1479 issue1.due_date = '2012-10-23'
1479 issue1.due_date = '2012-10-23'
1480 issue1.save!
1480 issue1.save!
1481 issue2.reload
1481 issue2.reload
1482 assert_equal Date.parse('2012-10-24'), issue2.start_date
1482 assert_equal Date.parse('2012-10-24'), issue2.start_date
1483 assert_equal Date.parse('2012-10-26'), issue2.due_date
1483 assert_equal Date.parse('2012-10-26'), issue2.due_date
1484 end
1484 end
1485
1485
1486 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1486 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1487 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1487 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1488 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1488 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1489 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1489 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1490 :relation_type => IssueRelation::TYPE_PRECEDES)
1490 :relation_type => IssueRelation::TYPE_PRECEDES)
1491 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1491 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1492
1492
1493 issue1.reload
1493 issue1.reload
1494 issue1.start_date = '2012-09-17'
1494 issue1.start_date = '2012-09-17'
1495 issue1.due_date = '2012-09-18'
1495 issue1.due_date = '2012-09-18'
1496 issue1.save!
1496 issue1.save!
1497 issue2.reload
1497 issue2.reload
1498 assert_equal Date.parse('2012-09-19'), issue2.start_date
1498 assert_equal Date.parse('2012-09-19'), issue2.start_date
1499 assert_equal Date.parse('2012-09-21'), issue2.due_date
1499 assert_equal Date.parse('2012-09-21'), issue2.due_date
1500 end
1500 end
1501
1501
1502 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1502 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1503 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1503 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1504 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1504 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1505 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1505 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1506 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1506 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1507 :relation_type => IssueRelation::TYPE_PRECEDES)
1507 :relation_type => IssueRelation::TYPE_PRECEDES)
1508 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1508 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1509 :relation_type => IssueRelation::TYPE_PRECEDES)
1509 :relation_type => IssueRelation::TYPE_PRECEDES)
1510 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1510 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1511
1511
1512 issue1.reload
1512 issue1.reload
1513 issue1.start_date = '2012-09-17'
1513 issue1.start_date = '2012-09-17'
1514 issue1.due_date = '2012-09-18'
1514 issue1.due_date = '2012-09-18'
1515 issue1.save!
1515 issue1.save!
1516 issue2.reload
1516 issue2.reload
1517 # Issue 2 must start after Issue 3
1517 # Issue 2 must start after Issue 3
1518 assert_equal Date.parse('2012-10-03'), issue2.start_date
1518 assert_equal Date.parse('2012-10-03'), issue2.start_date
1519 assert_equal Date.parse('2012-10-05'), issue2.due_date
1519 assert_equal Date.parse('2012-10-05'), issue2.due_date
1520 end
1520 end
1521
1521
1522 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1522 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1523 with_settings :non_working_week_days => [] do
1523 with_settings :non_working_week_days => [] do
1524 stale = Issue.find(1)
1524 stale = Issue.find(1)
1525 issue = Issue.find(1)
1525 issue = Issue.find(1)
1526 issue.subject = "Updated"
1526 issue.subject = "Updated"
1527 issue.save!
1527 issue.save!
1528 date = 10.days.from_now.to_date
1528 date = 10.days.from_now.to_date
1529 assert_nothing_raised do
1529 assert_nothing_raised do
1530 stale.reschedule_on!(date)
1530 stale.reschedule_on!(date)
1531 end
1531 end
1532 assert_equal date, stale.reload.start_date
1532 assert_equal date, stale.reload.start_date
1533 end
1533 end
1534 end
1534 end
1535
1535
1536 def test_child_issue_should_consider_parent_soonest_start_on_create
1536 def test_child_issue_should_consider_parent_soonest_start_on_create
1537 set_language_if_valid 'en'
1537 set_language_if_valid 'en'
1538 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1538 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1539 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1539 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1540 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1540 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1541 :relation_type => IssueRelation::TYPE_PRECEDES)
1541 :relation_type => IssueRelation::TYPE_PRECEDES)
1542 issue1.reload
1542 issue1.reload
1543 issue2.reload
1543 issue2.reload
1544 assert_equal Date.parse('2012-10-18'), issue2.start_date
1544 assert_equal Date.parse('2012-10-18'), issue2.start_date
1545
1545
1546 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1546 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1547 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1547 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1548 assert !child.valid?
1548 assert !child.valid?
1549 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1549 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1550 assert_equal Date.parse('2012-10-18'), child.soonest_start
1550 assert_equal Date.parse('2012-10-18'), child.soonest_start
1551 child.start_date = '2012-10-18'
1551 child.start_date = '2012-10-18'
1552 assert child.save
1552 assert child.save
1553 end
1553 end
1554
1554
1555 def test_setting_parent_to_a_dependent_issue_should_not_validate
1555 def test_setting_parent_to_a_dependent_issue_should_not_validate
1556 set_language_if_valid 'en'
1556 set_language_if_valid 'en'
1557 issue1 = Issue.generate!
1557 issue1 = Issue.generate!
1558 issue2 = Issue.generate!
1558 issue2 = Issue.generate!
1559 issue3 = Issue.generate!
1559 issue3 = Issue.generate!
1560 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1560 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1561 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1561 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1562 issue3.reload
1562 issue3.reload
1563 issue3.parent_issue_id = issue2.id
1563 issue3.parent_issue_id = issue2.id
1564 assert !issue3.valid?
1564 assert !issue3.valid?
1565 assert_include 'Parent task is invalid', issue3.errors.full_messages
1565 assert_include 'Parent task is invalid', issue3.errors.full_messages
1566 end
1566 end
1567
1567
1568 def test_setting_parent_should_not_allow_circular_dependency
1568 def test_setting_parent_should_not_allow_circular_dependency
1569 set_language_if_valid 'en'
1569 set_language_if_valid 'en'
1570 issue1 = Issue.generate!
1570 issue1 = Issue.generate!
1571 issue2 = Issue.generate!
1571 issue2 = Issue.generate!
1572 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1572 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1573 issue3 = Issue.generate!
1573 issue3 = Issue.generate!
1574 issue2.reload
1574 issue2.reload
1575 issue2.parent_issue_id = issue3.id
1575 issue2.parent_issue_id = issue3.id
1576 issue2.save!
1576 issue2.save!
1577 issue4 = Issue.generate!
1577 issue4 = Issue.generate!
1578 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1578 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1579 issue4.reload
1579 issue4.reload
1580 issue4.parent_issue_id = issue1.id
1580 issue4.parent_issue_id = issue1.id
1581 assert !issue4.valid?
1581 assert !issue4.valid?
1582 assert_include 'Parent task is invalid', issue4.errors.full_messages
1582 assert_include 'Parent task is invalid', issue4.errors.full_messages
1583 end
1583 end
1584
1584
1585 def test_overdue
1585 def test_overdue
1586 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1586 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1587 assert !Issue.new(:due_date => Date.today).overdue?
1587 assert !Issue.new(:due_date => Date.today).overdue?
1588 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1588 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1589 assert !Issue.new(:due_date => nil).overdue?
1589 assert !Issue.new(:due_date => nil).overdue?
1590 assert !Issue.new(:due_date => 1.day.ago.to_date,
1590 assert !Issue.new(:due_date => 1.day.ago.to_date,
1591 :status => IssueStatus.where(:is_closed => true).first
1591 :status => IssueStatus.where(:is_closed => true).first
1592 ).overdue?
1592 ).overdue?
1593 end
1593 end
1594
1594
1595 test "#behind_schedule? should be false if the issue has no start_date" do
1595 test "#behind_schedule? should be false if the issue has no start_date" do
1596 assert !Issue.new(:start_date => nil,
1596 assert !Issue.new(:start_date => nil,
1597 :due_date => 1.day.from_now.to_date,
1597 :due_date => 1.day.from_now.to_date,
1598 :done_ratio => 0).behind_schedule?
1598 :done_ratio => 0).behind_schedule?
1599 end
1599 end
1600
1600
1601 test "#behind_schedule? should be false if the issue has no end_date" do
1601 test "#behind_schedule? should be false if the issue has no end_date" do
1602 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1602 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1603 :due_date => nil,
1603 :due_date => nil,
1604 :done_ratio => 0).behind_schedule?
1604 :done_ratio => 0).behind_schedule?
1605 end
1605 end
1606
1606
1607 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1607 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1608 assert !Issue.new(:start_date => 50.days.ago.to_date,
1608 assert !Issue.new(:start_date => 50.days.ago.to_date,
1609 :due_date => 50.days.from_now.to_date,
1609 :due_date => 50.days.from_now.to_date,
1610 :done_ratio => 90).behind_schedule?
1610 :done_ratio => 90).behind_schedule?
1611 end
1611 end
1612
1612
1613 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1613 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1614 assert Issue.new(:start_date => 1.day.ago.to_date,
1614 assert Issue.new(:start_date => 1.day.ago.to_date,
1615 :due_date => 1.day.from_now.to_date,
1615 :due_date => 1.day.from_now.to_date,
1616 :done_ratio => 0).behind_schedule?
1616 :done_ratio => 0).behind_schedule?
1617 end
1617 end
1618
1618
1619 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1619 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1620 assert Issue.new(:start_date => 100.days.ago.to_date,
1620 assert Issue.new(:start_date => 100.days.ago.to_date,
1621 :due_date => Date.today,
1621 :due_date => Date.today,
1622 :done_ratio => 90).behind_schedule?
1622 :done_ratio => 90).behind_schedule?
1623 end
1623 end
1624
1624
1625 test "#assignable_users should be Users" do
1625 test "#assignable_users should be Users" do
1626 assert_kind_of User, Issue.find(1).assignable_users.first
1626 assert_kind_of User, Issue.find(1).assignable_users.first
1627 end
1627 end
1628
1628
1629 test "#assignable_users should include the issue author" do
1629 test "#assignable_users should include the issue author" do
1630 non_project_member = User.generate!
1630 non_project_member = User.generate!
1631 issue = Issue.generate!(:author => non_project_member)
1631 issue = Issue.generate!(:author => non_project_member)
1632
1632
1633 assert issue.assignable_users.include?(non_project_member)
1633 assert issue.assignable_users.include?(non_project_member)
1634 end
1634 end
1635
1635
1636 test "#assignable_users should include the current assignee" do
1636 test "#assignable_users should include the current assignee" do
1637 user = User.generate!
1637 user = User.generate!
1638 issue = Issue.generate!(:assigned_to => user)
1638 issue = Issue.generate!(:assigned_to => user)
1639 user.lock!
1639 user.lock!
1640
1640
1641 assert Issue.find(issue.id).assignable_users.include?(user)
1641 assert Issue.find(issue.id).assignable_users.include?(user)
1642 end
1642 end
1643
1643
1644 test "#assignable_users should not show the issue author twice" do
1644 test "#assignable_users should not show the issue author twice" do
1645 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1645 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1646 assert_equal 2, assignable_user_ids.length
1646 assert_equal 2, assignable_user_ids.length
1647
1647
1648 assignable_user_ids.each do |user_id|
1648 assignable_user_ids.each do |user_id|
1649 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1649 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1650 "User #{user_id} appears more or less than once"
1650 "User #{user_id} appears more or less than once"
1651 end
1651 end
1652 end
1652 end
1653
1653
1654 test "#assignable_users with issue_group_assignment should include groups" do
1654 test "#assignable_users with issue_group_assignment should include groups" do
1655 issue = Issue.new(:project => Project.find(2))
1655 issue = Issue.new(:project => Project.find(2))
1656
1656
1657 with_settings :issue_group_assignment => '1' do
1657 with_settings :issue_group_assignment => '1' do
1658 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1658 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1659 assert issue.assignable_users.include?(Group.find(11))
1659 assert issue.assignable_users.include?(Group.find(11))
1660 end
1660 end
1661 end
1661 end
1662
1662
1663 test "#assignable_users without issue_group_assignment should not include groups" do
1663 test "#assignable_users without issue_group_assignment should not include groups" do
1664 issue = Issue.new(:project => Project.find(2))
1664 issue = Issue.new(:project => Project.find(2))
1665
1665
1666 with_settings :issue_group_assignment => '0' do
1666 with_settings :issue_group_assignment => '0' do
1667 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1667 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1668 assert !issue.assignable_users.include?(Group.find(11))
1668 assert !issue.assignable_users.include?(Group.find(11))
1669 end
1669 end
1670 end
1670 end
1671
1671
1672 def test_create_should_send_email_notification
1672 def test_create_should_send_email_notification
1673 ActionMailer::Base.deliveries.clear
1673 ActionMailer::Base.deliveries.clear
1674 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1674 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1675 :author_id => 3, :status_id => 1,
1675 :author_id => 3, :status_id => 1,
1676 :priority => IssuePriority.all.first,
1676 :priority => IssuePriority.all.first,
1677 :subject => 'test_create', :estimated_hours => '1:30')
1677 :subject => 'test_create', :estimated_hours => '1:30')
1678
1678
1679 assert issue.save
1679 assert issue.save
1680 assert_equal 1, ActionMailer::Base.deliveries.size
1680 assert_equal 1, ActionMailer::Base.deliveries.size
1681 end
1681 end
1682
1682
1683 def test_stale_issue_should_not_send_email_notification
1683 def test_stale_issue_should_not_send_email_notification
1684 ActionMailer::Base.deliveries.clear
1684 ActionMailer::Base.deliveries.clear
1685 issue = Issue.find(1)
1685 issue = Issue.find(1)
1686 stale = Issue.find(1)
1686 stale = Issue.find(1)
1687
1687
1688 issue.init_journal(User.find(1))
1688 issue.init_journal(User.find(1))
1689 issue.subject = 'Subjet update'
1689 issue.subject = 'Subjet update'
1690 assert issue.save
1690 assert issue.save
1691 assert_equal 1, ActionMailer::Base.deliveries.size
1691 assert_equal 1, ActionMailer::Base.deliveries.size
1692 ActionMailer::Base.deliveries.clear
1692 ActionMailer::Base.deliveries.clear
1693
1693
1694 stale.init_journal(User.find(1))
1694 stale.init_journal(User.find(1))
1695 stale.subject = 'Another subjet update'
1695 stale.subject = 'Another subjet update'
1696 assert_raise ActiveRecord::StaleObjectError do
1696 assert_raise ActiveRecord::StaleObjectError do
1697 stale.save
1697 stale.save
1698 end
1698 end
1699 assert ActionMailer::Base.deliveries.empty?
1699 assert ActionMailer::Base.deliveries.empty?
1700 end
1700 end
1701
1701
1702 def test_journalized_description
1702 def test_journalized_description
1703 IssueCustomField.delete_all
1703 IssueCustomField.delete_all
1704
1704
1705 i = Issue.first
1705 i = Issue.first
1706 old_description = i.description
1706 old_description = i.description
1707 new_description = "This is the new description"
1707 new_description = "This is the new description"
1708
1708
1709 i.init_journal(User.find(2))
1709 i.init_journal(User.find(2))
1710 i.description = new_description
1710 i.description = new_description
1711 assert_difference 'Journal.count', 1 do
1711 assert_difference 'Journal.count', 1 do
1712 assert_difference 'JournalDetail.count', 1 do
1712 assert_difference 'JournalDetail.count', 1 do
1713 i.save!
1713 i.save!
1714 end
1714 end
1715 end
1715 end
1716
1716
1717 detail = JournalDetail.first(:order => 'id DESC')
1717 detail = JournalDetail.first(:order => 'id DESC')
1718 assert_equal i, detail.journal.journalized
1718 assert_equal i, detail.journal.journalized
1719 assert_equal 'attr', detail.property
1719 assert_equal 'attr', detail.property
1720 assert_equal 'description', detail.prop_key
1720 assert_equal 'description', detail.prop_key
1721 assert_equal old_description, detail.old_value
1721 assert_equal old_description, detail.old_value
1722 assert_equal new_description, detail.value
1722 assert_equal new_description, detail.value
1723 end
1723 end
1724
1724
1725 def test_blank_descriptions_should_not_be_journalized
1725 def test_blank_descriptions_should_not_be_journalized
1726 IssueCustomField.delete_all
1726 IssueCustomField.delete_all
1727 Issue.update_all("description = NULL", "id=1")
1727 Issue.update_all("description = NULL", "id=1")
1728
1728
1729 i = Issue.find(1)
1729 i = Issue.find(1)
1730 i.init_journal(User.find(2))
1730 i.init_journal(User.find(2))
1731 i.subject = "blank description"
1731 i.subject = "blank description"
1732 i.description = "\r\n"
1732 i.description = "\r\n"
1733
1733
1734 assert_difference 'Journal.count', 1 do
1734 assert_difference 'Journal.count', 1 do
1735 assert_difference 'JournalDetail.count', 1 do
1735 assert_difference 'JournalDetail.count', 1 do
1736 i.save!
1736 i.save!
1737 end
1737 end
1738 end
1738 end
1739 end
1739 end
1740
1740
1741 def test_journalized_multi_custom_field
1741 def test_journalized_multi_custom_field
1742 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1742 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1743 :is_filter => true, :is_for_all => true,
1743 :is_filter => true, :is_for_all => true,
1744 :tracker_ids => [1],
1744 :tracker_ids => [1],
1745 :possible_values => ['value1', 'value2', 'value3'],
1745 :possible_values => ['value1', 'value2', 'value3'],
1746 :multiple => true)
1746 :multiple => true)
1747
1747
1748 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1748 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1749 :subject => 'Test', :author_id => 1)
1749 :subject => 'Test', :author_id => 1)
1750
1750
1751 assert_difference 'Journal.count' do
1751 assert_difference 'Journal.count' do
1752 assert_difference 'JournalDetail.count' do
1752 assert_difference 'JournalDetail.count' do
1753 issue.init_journal(User.first)
1753 issue.init_journal(User.first)
1754 issue.custom_field_values = {field.id => ['value1']}
1754 issue.custom_field_values = {field.id => ['value1']}
1755 issue.save!
1755 issue.save!
1756 end
1756 end
1757 assert_difference 'JournalDetail.count' do
1757 assert_difference 'JournalDetail.count' do
1758 issue.init_journal(User.first)
1758 issue.init_journal(User.first)
1759 issue.custom_field_values = {field.id => ['value1', 'value2']}
1759 issue.custom_field_values = {field.id => ['value1', 'value2']}
1760 issue.save!
1760 issue.save!
1761 end
1761 end
1762 assert_difference 'JournalDetail.count', 2 do
1762 assert_difference 'JournalDetail.count', 2 do
1763 issue.init_journal(User.first)
1763 issue.init_journal(User.first)
1764 issue.custom_field_values = {field.id => ['value3', 'value2']}
1764 issue.custom_field_values = {field.id => ['value3', 'value2']}
1765 issue.save!
1765 issue.save!
1766 end
1766 end
1767 assert_difference 'JournalDetail.count', 2 do
1767 assert_difference 'JournalDetail.count', 2 do
1768 issue.init_journal(User.first)
1768 issue.init_journal(User.first)
1769 issue.custom_field_values = {field.id => nil}
1769 issue.custom_field_values = {field.id => nil}
1770 issue.save!
1770 issue.save!
1771 end
1771 end
1772 end
1772 end
1773 end
1773 end
1774
1774
1775 def test_description_eol_should_be_normalized
1775 def test_description_eol_should_be_normalized
1776 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1776 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1777 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1777 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1778 end
1778 end
1779
1779
1780 def test_saving_twice_should_not_duplicate_journal_details
1780 def test_saving_twice_should_not_duplicate_journal_details
1781 i = Issue.first
1781 i = Issue.first
1782 i.init_journal(User.find(2), 'Some notes')
1782 i.init_journal(User.find(2), 'Some notes')
1783 # initial changes
1783 # initial changes
1784 i.subject = 'New subject'
1784 i.subject = 'New subject'
1785 i.done_ratio = i.done_ratio + 10
1785 i.done_ratio = i.done_ratio + 10
1786 assert_difference 'Journal.count' do
1786 assert_difference 'Journal.count' do
1787 assert i.save
1787 assert i.save
1788 end
1788 end
1789 # 1 more change
1789 # 1 more change
1790 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1790 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1791 assert_no_difference 'Journal.count' do
1791 assert_no_difference 'Journal.count' do
1792 assert_difference 'JournalDetail.count', 1 do
1792 assert_difference 'JournalDetail.count', 1 do
1793 i.save
1793 i.save
1794 end
1794 end
1795 end
1795 end
1796 # no more change
1796 # no more change
1797 assert_no_difference 'Journal.count' do
1797 assert_no_difference 'Journal.count' do
1798 assert_no_difference 'JournalDetail.count' do
1798 assert_no_difference 'JournalDetail.count' do
1799 i.save
1799 i.save
1800 end
1800 end
1801 end
1801 end
1802 end
1802 end
1803
1803
1804 def test_all_dependent_issues
1804 def test_all_dependent_issues
1805 IssueRelation.delete_all
1805 IssueRelation.delete_all
1806 assert IssueRelation.create!(:issue_from => Issue.find(1),
1806 assert IssueRelation.create!(:issue_from => Issue.find(1),
1807 :issue_to => Issue.find(2),
1807 :issue_to => Issue.find(2),
1808 :relation_type => IssueRelation::TYPE_PRECEDES)
1808 :relation_type => IssueRelation::TYPE_PRECEDES)
1809 assert IssueRelation.create!(:issue_from => Issue.find(2),
1809 assert IssueRelation.create!(:issue_from => Issue.find(2),
1810 :issue_to => Issue.find(3),
1810 :issue_to => Issue.find(3),
1811 :relation_type => IssueRelation::TYPE_PRECEDES)
1811 :relation_type => IssueRelation::TYPE_PRECEDES)
1812 assert IssueRelation.create!(:issue_from => Issue.find(3),
1812 assert IssueRelation.create!(:issue_from => Issue.find(3),
1813 :issue_to => Issue.find(8),
1813 :issue_to => Issue.find(8),
1814 :relation_type => IssueRelation::TYPE_PRECEDES)
1814 :relation_type => IssueRelation::TYPE_PRECEDES)
1815
1815
1816 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1816 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1817 end
1817 end
1818
1818
1819 def test_all_dependent_issues_with_subtask
1819 def test_all_dependent_issues_with_subtask
1820 IssueRelation.delete_all
1820 IssueRelation.delete_all
1821
1821
1822 project = Project.generate!(:name => "testproject")
1822 project = Project.generate!(:name => "testproject")
1823
1823
1824 parentIssue = Issue.generate!(:project => project)
1824 parentIssue = Issue.generate!(:project => project)
1825 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1825 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1826 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1826 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1827
1827
1828 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
1828 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
1829 end
1829 end
1830
1830
1831 def test_all_dependent_issues_does_not_include_self
1831 def test_all_dependent_issues_does_not_include_self
1832 IssueRelation.delete_all
1832 IssueRelation.delete_all
1833
1833
1834 project = Project.generate!(:name => "testproject")
1834 project = Project.generate!(:name => "testproject")
1835
1835
1836 parentIssue = Issue.generate!(:project => project)
1836 parentIssue = Issue.generate!(:project => project)
1837 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1837 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1838
1838
1839 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
1839 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
1840 end
1840 end
1841
1841
1842 def test_all_dependent_issues_with_parenttask_and_sibling
1842 def test_all_dependent_issues_with_parenttask_and_sibling
1843 IssueRelation.delete_all
1843 IssueRelation.delete_all
1844
1844
1845 project = Project.generate!(:name => "testproject")
1845 project = Project.generate!(:name => "testproject")
1846
1846
1847 parentIssue = Issue.generate!(:project => project)
1847 parentIssue = Issue.generate!(:project => project)
1848 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1848 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1849 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1849 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1850
1850
1851 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
1851 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
1852 end
1852 end
1853
1853
1854 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
1854 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
1855 IssueRelation.delete_all
1855 IssueRelation.delete_all
1856
1856
1857 project = Project.generate!(:name => "testproject")
1857 project = Project.generate!(:name => "testproject")
1858
1858
1859 parentIssue1 = Issue.generate!(:project => project)
1859 parentIssue1 = Issue.generate!(:project => project)
1860 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1860 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1861 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1861 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1862
1862
1863 parentIssue2 = Issue.generate!(:project => project)
1863 parentIssue2 = Issue.generate!(:project => project)
1864 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1864 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1865 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1865 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1866
1866
1867
1867
1868 assert IssueRelation.create(:issue_from => parentIssue1,
1868 assert IssueRelation.create(:issue_from => parentIssue1,
1869 :issue_to => childIssue2_2,
1869 :issue_to => childIssue2_2,
1870 :relation_type => IssueRelation::TYPE_BLOCKS)
1870 :relation_type => IssueRelation::TYPE_BLOCKS)
1871
1871
1872 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
1872 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
1873 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1873 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1874 end
1874 end
1875
1875
1876 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
1876 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
1877 IssueRelation.delete_all
1877 IssueRelation.delete_all
1878
1878
1879 project = Project.generate!(:name => "testproject")
1879 project = Project.generate!(:name => "testproject")
1880
1880
1881 parentIssue1 = Issue.generate!(:project => project)
1881 parentIssue1 = Issue.generate!(:project => project)
1882 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1882 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1883 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1883 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1884
1884
1885 parentIssue2 = Issue.generate!(:project => project)
1885 parentIssue2 = Issue.generate!(:project => project)
1886 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1886 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1887 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1887 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1888
1888
1889
1889
1890 assert IssueRelation.create(:issue_from => parentIssue1,
1890 assert IssueRelation.create(:issue_from => parentIssue1,
1891 :issue_to => parentIssue2,
1891 :issue_to => parentIssue2,
1892 :relation_type => IssueRelation::TYPE_BLOCKS)
1892 :relation_type => IssueRelation::TYPE_BLOCKS)
1893
1893
1894 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
1894 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
1895 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1895 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1896 end
1896 end
1897
1897
1898 def test_all_dependent_issues_with_transitive_relation
1898 def test_all_dependent_issues_with_transitive_relation
1899 IssueRelation.delete_all
1899 IssueRelation.delete_all
1900
1900
1901 project = Project.generate!(:name => "testproject")
1901 project = Project.generate!(:name => "testproject")
1902
1902
1903 parentIssue1 = Issue.generate!(:project => project)
1903 parentIssue1 = Issue.generate!(:project => project)
1904 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1904 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1905
1905
1906 parentIssue2 = Issue.generate!(:project => project)
1906 parentIssue2 = Issue.generate!(:project => project)
1907 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1907 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1908
1908
1909 independentIssue = Issue.generate!(:project => project)
1909 independentIssue = Issue.generate!(:project => project)
1910
1910
1911 assert IssueRelation.create(:issue_from => parentIssue1,
1911 assert IssueRelation.create(:issue_from => parentIssue1,
1912 :issue_to => childIssue2_1,
1912 :issue_to => childIssue2_1,
1913 :relation_type => IssueRelation::TYPE_RELATES)
1913 :relation_type => IssueRelation::TYPE_RELATES)
1914
1914
1915 assert IssueRelation.create(:issue_from => childIssue2_1,
1915 assert IssueRelation.create(:issue_from => childIssue2_1,
1916 :issue_to => independentIssue,
1916 :issue_to => independentIssue,
1917 :relation_type => IssueRelation::TYPE_RELATES)
1917 :relation_type => IssueRelation::TYPE_RELATES)
1918
1918
1919 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1919 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1920 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1920 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1921 end
1921 end
1922
1922
1923 def test_all_dependent_issues_with_transitive_relation2
1923 def test_all_dependent_issues_with_transitive_relation2
1924 IssueRelation.delete_all
1924 IssueRelation.delete_all
1925
1925
1926 project = Project.generate!(:name => "testproject")
1926 project = Project.generate!(:name => "testproject")
1927
1927
1928 parentIssue1 = Issue.generate!(:project => project)
1928 parentIssue1 = Issue.generate!(:project => project)
1929 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1929 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1930
1930
1931 parentIssue2 = Issue.generate!(:project => project)
1931 parentIssue2 = Issue.generate!(:project => project)
1932 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1932 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1933
1933
1934 independentIssue = Issue.generate!(:project => project)
1934 independentIssue = Issue.generate!(:project => project)
1935
1935
1936 assert IssueRelation.create(:issue_from => parentIssue1,
1936 assert IssueRelation.create(:issue_from => parentIssue1,
1937 :issue_to => independentIssue,
1937 :issue_to => independentIssue,
1938 :relation_type => IssueRelation::TYPE_RELATES)
1938 :relation_type => IssueRelation::TYPE_RELATES)
1939
1939
1940 assert IssueRelation.create(:issue_from => independentIssue,
1940 assert IssueRelation.create(:issue_from => independentIssue,
1941 :issue_to => childIssue2_1,
1941 :issue_to => childIssue2_1,
1942 :relation_type => IssueRelation::TYPE_RELATES)
1942 :relation_type => IssueRelation::TYPE_RELATES)
1943
1943
1944 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1944 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1945 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1945 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1946
1946
1947 end
1947 end
1948
1948
1949 def test_all_dependent_issues_with_persistent_circular_dependency
1949 def test_all_dependent_issues_with_persistent_circular_dependency
1950 IssueRelation.delete_all
1950 IssueRelation.delete_all
1951 assert IssueRelation.create!(:issue_from => Issue.find(1),
1951 assert IssueRelation.create!(:issue_from => Issue.find(1),
1952 :issue_to => Issue.find(2),
1952 :issue_to => Issue.find(2),
1953 :relation_type => IssueRelation::TYPE_PRECEDES)
1953 :relation_type => IssueRelation::TYPE_PRECEDES)
1954 assert IssueRelation.create!(:issue_from => Issue.find(2),
1954 assert IssueRelation.create!(:issue_from => Issue.find(2),
1955 :issue_to => Issue.find(3),
1955 :issue_to => Issue.find(3),
1956 :relation_type => IssueRelation::TYPE_PRECEDES)
1956 :relation_type => IssueRelation::TYPE_PRECEDES)
1957
1957
1958 r = IssueRelation.create!(:issue_from => Issue.find(3),
1958 r = IssueRelation.create!(:issue_from => Issue.find(3),
1959 :issue_to => Issue.find(7),
1959 :issue_to => Issue.find(7),
1960 :relation_type => IssueRelation::TYPE_PRECEDES)
1960 :relation_type => IssueRelation::TYPE_PRECEDES)
1961 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1961 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1962
1962
1963 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1963 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1964 end
1964 end
1965
1965
1966 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1966 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1967 IssueRelation.delete_all
1967 IssueRelation.delete_all
1968 assert IssueRelation.create!(:issue_from => Issue.find(1),
1968 assert IssueRelation.create!(:issue_from => Issue.find(1),
1969 :issue_to => Issue.find(2),
1969 :issue_to => Issue.find(2),
1970 :relation_type => IssueRelation::TYPE_RELATES)
1970 :relation_type => IssueRelation::TYPE_RELATES)
1971 assert IssueRelation.create!(:issue_from => Issue.find(2),
1971 assert IssueRelation.create!(:issue_from => Issue.find(2),
1972 :issue_to => Issue.find(3),
1972 :issue_to => Issue.find(3),
1973 :relation_type => IssueRelation::TYPE_RELATES)
1973 :relation_type => IssueRelation::TYPE_RELATES)
1974 assert IssueRelation.create!(:issue_from => Issue.find(3),
1974 assert IssueRelation.create!(:issue_from => Issue.find(3),
1975 :issue_to => Issue.find(8),
1975 :issue_to => Issue.find(8),
1976 :relation_type => IssueRelation::TYPE_RELATES)
1976 :relation_type => IssueRelation::TYPE_RELATES)
1977
1977
1978 r = IssueRelation.create!(:issue_from => Issue.find(8),
1978 r = IssueRelation.create!(:issue_from => Issue.find(8),
1979 :issue_to => Issue.find(7),
1979 :issue_to => Issue.find(7),
1980 :relation_type => IssueRelation::TYPE_RELATES)
1980 :relation_type => IssueRelation::TYPE_RELATES)
1981 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1981 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1982
1982
1983 r = IssueRelation.create!(:issue_from => Issue.find(3),
1983 r = IssueRelation.create!(:issue_from => Issue.find(3),
1984 :issue_to => Issue.find(7),
1984 :issue_to => Issue.find(7),
1985 :relation_type => IssueRelation::TYPE_RELATES)
1985 :relation_type => IssueRelation::TYPE_RELATES)
1986 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1986 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1987
1987
1988 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1988 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1989 end
1989 end
1990
1990
1991 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
1991 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
1992 @issue = Issue.find(1)
1992 @issue = Issue.find(1)
1993 @issue_status = IssueStatus.find(1)
1993 @issue_status = IssueStatus.find(1)
1994 @issue_status.update_attribute(:default_done_ratio, 50)
1994 @issue_status.update_attribute(:default_done_ratio, 50)
1995 @issue2 = Issue.find(2)
1995 @issue2 = Issue.find(2)
1996 @issue_status2 = IssueStatus.find(2)
1996 @issue_status2 = IssueStatus.find(2)
1997 @issue_status2.update_attribute(:default_done_ratio, 0)
1997 @issue_status2.update_attribute(:default_done_ratio, 0)
1998
1998
1999 with_settings :issue_done_ratio => 'issue_field' do
1999 with_settings :issue_done_ratio => 'issue_field' do
2000 assert_equal 0, @issue.done_ratio
2000 assert_equal 0, @issue.done_ratio
2001 assert_equal 30, @issue2.done_ratio
2001 assert_equal 30, @issue2.done_ratio
2002 end
2002 end
2003
2003
2004 with_settings :issue_done_ratio => 'issue_status' do
2004 with_settings :issue_done_ratio => 'issue_status' do
2005 assert_equal 50, @issue.done_ratio
2005 assert_equal 50, @issue.done_ratio
2006 assert_equal 0, @issue2.done_ratio
2006 assert_equal 0, @issue2.done_ratio
2007 end
2007 end
2008 end
2008 end
2009
2009
2010 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2010 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2011 @issue = Issue.find(1)
2011 @issue = Issue.find(1)
2012 @issue_status = IssueStatus.find(1)
2012 @issue_status = IssueStatus.find(1)
2013 @issue_status.update_attribute(:default_done_ratio, 50)
2013 @issue_status.update_attribute(:default_done_ratio, 50)
2014 @issue2 = Issue.find(2)
2014 @issue2 = Issue.find(2)
2015 @issue_status2 = IssueStatus.find(2)
2015 @issue_status2 = IssueStatus.find(2)
2016 @issue_status2.update_attribute(:default_done_ratio, 0)
2016 @issue_status2.update_attribute(:default_done_ratio, 0)
2017
2017
2018 with_settings :issue_done_ratio => 'issue_field' do
2018 with_settings :issue_done_ratio => 'issue_field' do
2019 @issue.update_done_ratio_from_issue_status
2019 @issue.update_done_ratio_from_issue_status
2020 @issue2.update_done_ratio_from_issue_status
2020 @issue2.update_done_ratio_from_issue_status
2021
2021
2022 assert_equal 0, @issue.read_attribute(:done_ratio)
2022 assert_equal 0, @issue.read_attribute(:done_ratio)
2023 assert_equal 30, @issue2.read_attribute(:done_ratio)
2023 assert_equal 30, @issue2.read_attribute(:done_ratio)
2024 end
2024 end
2025
2025
2026 with_settings :issue_done_ratio => 'issue_status' do
2026 with_settings :issue_done_ratio => 'issue_status' do
2027 @issue.update_done_ratio_from_issue_status
2027 @issue.update_done_ratio_from_issue_status
2028 @issue2.update_done_ratio_from_issue_status
2028 @issue2.update_done_ratio_from_issue_status
2029
2029
2030 assert_equal 50, @issue.read_attribute(:done_ratio)
2030 assert_equal 50, @issue.read_attribute(:done_ratio)
2031 assert_equal 0, @issue2.read_attribute(:done_ratio)
2031 assert_equal 0, @issue2.read_attribute(:done_ratio)
2032 end
2032 end
2033 end
2033 end
2034
2034
2035 test "#by_tracker" do
2035 test "#by_tracker" do
2036 User.current = User.anonymous
2036 User.current = User.anonymous
2037 groups = Issue.by_tracker(Project.find(1))
2037 groups = Issue.by_tracker(Project.find(1))
2038 assert_equal 3, groups.count
2038 assert_equal 3, groups.count
2039 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2039 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2040 end
2040 end
2041
2041
2042 test "#by_version" do
2042 test "#by_version" do
2043 User.current = User.anonymous
2043 User.current = User.anonymous
2044 groups = Issue.by_version(Project.find(1))
2044 groups = Issue.by_version(Project.find(1))
2045 assert_equal 3, groups.count
2045 assert_equal 3, groups.count
2046 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2046 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2047 end
2047 end
2048
2048
2049 test "#by_priority" do
2049 test "#by_priority" do
2050 User.current = User.anonymous
2050 User.current = User.anonymous
2051 groups = Issue.by_priority(Project.find(1))
2051 groups = Issue.by_priority(Project.find(1))
2052 assert_equal 4, groups.count
2052 assert_equal 4, groups.count
2053 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2053 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2054 end
2054 end
2055
2055
2056 test "#by_category" do
2056 test "#by_category" do
2057 User.current = User.anonymous
2057 User.current = User.anonymous
2058 groups = Issue.by_category(Project.find(1))
2058 groups = Issue.by_category(Project.find(1))
2059 assert_equal 2, groups.count
2059 assert_equal 2, groups.count
2060 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2060 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2061 end
2061 end
2062
2062
2063 test "#by_assigned_to" do
2063 test "#by_assigned_to" do
2064 User.current = User.anonymous
2064 User.current = User.anonymous
2065 groups = Issue.by_assigned_to(Project.find(1))
2065 groups = Issue.by_assigned_to(Project.find(1))
2066 assert_equal 2, groups.count
2066 assert_equal 2, groups.count
2067 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2067 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2068 end
2068 end
2069
2069
2070 test "#by_author" do
2070 test "#by_author" do
2071 User.current = User.anonymous
2071 User.current = User.anonymous
2072 groups = Issue.by_author(Project.find(1))
2072 groups = Issue.by_author(Project.find(1))
2073 assert_equal 4, groups.count
2073 assert_equal 4, groups.count
2074 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}
2075 end
2075 end
2076
2076
2077 test "#by_subproject" do
2077 test "#by_subproject" do
2078 User.current = User.anonymous
2078 User.current = User.anonymous
2079 groups = Issue.by_subproject(Project.find(1))
2079 groups = Issue.by_subproject(Project.find(1))
2080 # Private descendant not visible
2080 # Private descendant not visible
2081 assert_equal 1, groups.count
2081 assert_equal 1, groups.count
2082 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2082 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2083 end
2083 end
2084
2084
2085 def test_recently_updated_scope
2085 def test_recently_updated_scope
2086 #should return the last updated issue
2086 #should return the last updated issue
2087 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2087 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2088 end
2088 end
2089
2089
2090 def test_on_active_projects_scope
2090 def test_on_active_projects_scope
2091 assert Project.find(2).archive
2091 assert Project.find(2).archive
2092
2092
2093 before = Issue.on_active_project.length
2093 before = Issue.on_active_project.length
2094 # test inclusion to results
2094 # test inclusion to results
2095 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2095 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2096 assert_equal before + 1, Issue.on_active_project.length
2096 assert_equal before + 1, Issue.on_active_project.length
2097
2097
2098 # Move to an archived project
2098 # Move to an archived project
2099 issue.project = Project.find(2)
2099 issue.project = Project.find(2)
2100 assert issue.save
2100 assert issue.save
2101 assert_equal before, Issue.on_active_project.length
2101 assert_equal before, Issue.on_active_project.length
2102 end
2102 end
2103
2103
2104 test "Issue#recipients should include project recipients" do
2104 test "Issue#recipients should include project recipients" do
2105 issue = Issue.generate!
2105 issue = Issue.generate!
2106 assert issue.project.recipients.present?
2106 assert issue.project.recipients.present?
2107 issue.project.recipients.each do |project_recipient|
2107 issue.project.recipients.each do |project_recipient|
2108 assert issue.recipients.include?(project_recipient)
2108 assert issue.recipients.include?(project_recipient)
2109 end
2109 end
2110 end
2110 end
2111
2111
2112 test "Issue#recipients should include the author if the author is active" do
2112 test "Issue#recipients should include the author if the author is active" do
2113 issue = Issue.generate!(:author => User.generate!)
2113 issue = Issue.generate!(:author => User.generate!)
2114 assert issue.author, "No author set for Issue"
2114 assert issue.author, "No author set for Issue"
2115 assert issue.recipients.include?(issue.author.mail)
2115 assert issue.recipients.include?(issue.author.mail)
2116 end
2116 end
2117
2117
2118 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2118 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2119 issue = Issue.generate!(:assigned_to => User.generate!)
2119 issue = Issue.generate!(:assigned_to => User.generate!)
2120 assert issue.assigned_to, "No assigned_to set for Issue"
2120 assert issue.assigned_to, "No assigned_to set for Issue"
2121 assert issue.recipients.include?(issue.assigned_to.mail)
2121 assert issue.recipients.include?(issue.assigned_to.mail)
2122 end
2122 end
2123
2123
2124 test "Issue#recipients should not include users who opt out of all email" do
2124 test "Issue#recipients should not include users who opt out of all email" do
2125 issue = Issue.generate!(:author => User.generate!)
2125 issue = Issue.generate!(:author => User.generate!)
2126 issue.author.update_attribute(:mail_notification, :none)
2126 issue.author.update_attribute(:mail_notification, :none)
2127 assert !issue.recipients.include?(issue.author.mail)
2127 assert !issue.recipients.include?(issue.author.mail)
2128 end
2128 end
2129
2129
2130 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2130 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2131 issue = Issue.generate!(:author => User.generate!)
2131 issue = Issue.generate!(:author => User.generate!)
2132 issue.author.update_attribute(:mail_notification, :only_assigned)
2132 issue.author.update_attribute(:mail_notification, :only_assigned)
2133 assert !issue.recipients.include?(issue.author.mail)
2133 assert !issue.recipients.include?(issue.author.mail)
2134 end
2134 end
2135
2135
2136 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2136 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2137 issue = Issue.generate!(:assigned_to => User.generate!)
2137 issue = Issue.generate!(:assigned_to => User.generate!)
2138 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2138 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2139 assert !issue.recipients.include?(issue.assigned_to.mail)
2139 assert !issue.recipients.include?(issue.assigned_to.mail)
2140 end
2140 end
2141
2141
2142 def test_last_journal_id_with_journals_should_return_the_journal_id
2142 def test_last_journal_id_with_journals_should_return_the_journal_id
2143 assert_equal 2, Issue.find(1).last_journal_id
2143 assert_equal 2, Issue.find(1).last_journal_id
2144 end
2144 end
2145
2145
2146 def test_last_journal_id_without_journals_should_return_nil
2146 def test_last_journal_id_without_journals_should_return_nil
2147 assert_nil Issue.find(3).last_journal_id
2147 assert_nil Issue.find(3).last_journal_id
2148 end
2148 end
2149
2149
2150 def test_journals_after_should_return_journals_with_greater_id
2150 def test_journals_after_should_return_journals_with_greater_id
2151 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2151 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2152 assert_equal [], Issue.find(1).journals_after('2')
2152 assert_equal [], Issue.find(1).journals_after('2')
2153 end
2153 end
2154
2154
2155 def test_journals_after_with_blank_arg_should_return_all_journals
2155 def test_journals_after_with_blank_arg_should_return_all_journals
2156 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2156 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2157 end
2157 end
2158
2158
2159 def test_css_classes_should_include_tracker
2159 def test_css_classes_should_include_tracker
2160 issue = Issue.new(:tracker => Tracker.find(2))
2160 issue = Issue.new(:tracker => Tracker.find(2))
2161 classes = issue.css_classes.split(' ')
2161 classes = issue.css_classes.split(' ')
2162 assert_include 'tracker-2', classes
2162 assert_include 'tracker-2', classes
2163 end
2163 end
2164
2164
2165 def test_css_classes_should_include_priority
2165 def test_css_classes_should_include_priority
2166 issue = Issue.new(:priority => IssuePriority.find(8))
2166 issue = Issue.new(:priority => IssuePriority.find(8))
2167 classes = issue.css_classes.split(' ')
2167 classes = issue.css_classes.split(' ')
2168 assert_include 'priority-8', classes
2168 assert_include 'priority-8', classes
2169 assert_include 'priority-highest', classes
2169 assert_include 'priority-highest', classes
2170 end
2170 end
2171
2171
2172 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2172 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2173 set_tmp_attachments_directory
2173 set_tmp_attachments_directory
2174 issue = Issue.generate!
2174 issue = Issue.generate!
2175 issue.save_attachments({
2175 issue.save_attachments({
2176 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2176 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2177 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2177 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2178 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2178 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2179 })
2179 })
2180 issue.attach_saved_attachments
2180 issue.attach_saved_attachments
2181
2181
2182 assert_equal 3, issue.reload.attachments.count
2182 assert_equal 3, issue.reload.attachments.count
2183 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2183 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2184 end
2184 end
2185
2185
2186 def test_closed_on_should_be_nil_when_creating_an_open_issue
2186 def test_closed_on_should_be_nil_when_creating_an_open_issue
2187 issue = Issue.generate!(:status_id => 1).reload
2187 issue = Issue.generate!(:status_id => 1).reload
2188 assert !issue.closed?
2188 assert !issue.closed?
2189 assert_nil issue.closed_on
2189 assert_nil issue.closed_on
2190 end
2190 end
2191
2191
2192 def test_closed_on_should_be_set_when_creating_a_closed_issue
2192 def test_closed_on_should_be_set_when_creating_a_closed_issue
2193 issue = Issue.generate!(:status_id => 5).reload
2193 issue = Issue.generate!(:status_id => 5).reload
2194 assert issue.closed?
2194 assert issue.closed?
2195 assert_not_nil issue.closed_on
2195 assert_not_nil issue.closed_on
2196 assert_equal issue.updated_on, issue.closed_on
2196 assert_equal issue.updated_on, issue.closed_on
2197 assert_equal issue.created_on, issue.closed_on
2197 assert_equal issue.created_on, issue.closed_on
2198 end
2198 end
2199
2199
2200 def test_closed_on_should_be_nil_when_updating_an_open_issue
2200 def test_closed_on_should_be_nil_when_updating_an_open_issue
2201 issue = Issue.find(1)
2201 issue = Issue.find(1)
2202 issue.subject = 'Not closed yet'
2202 issue.subject = 'Not closed yet'
2203 issue.save!
2203 issue.save!
2204 issue.reload
2204 issue.reload
2205 assert_nil issue.closed_on
2205 assert_nil issue.closed_on
2206 end
2206 end
2207
2207
2208 def test_closed_on_should_be_set_when_closing_an_open_issue
2208 def test_closed_on_should_be_set_when_closing_an_open_issue
2209 issue = Issue.find(1)
2209 issue = Issue.find(1)
2210 issue.subject = 'Now closed'
2210 issue.subject = 'Now closed'
2211 issue.status_id = 5
2211 issue.status_id = 5
2212 issue.save!
2212 issue.save!
2213 issue.reload
2213 issue.reload
2214 assert_not_nil issue.closed_on
2214 assert_not_nil issue.closed_on
2215 assert_equal issue.updated_on, issue.closed_on
2215 assert_equal issue.updated_on, issue.closed_on
2216 end
2216 end
2217
2217
2218 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2218 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2219 issue = Issue.open(false).first
2219 issue = Issue.open(false).first
2220 was_closed_on = issue.closed_on
2220 was_closed_on = issue.closed_on
2221 assert_not_nil was_closed_on
2221 assert_not_nil was_closed_on
2222 issue.subject = 'Updating a closed issue'
2222 issue.subject = 'Updating a closed issue'
2223 issue.save!
2223 issue.save!
2224 issue.reload
2224 issue.reload
2225 assert_equal was_closed_on, issue.closed_on
2225 assert_equal was_closed_on, issue.closed_on
2226 end
2226 end
2227
2227
2228 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2228 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2229 issue = Issue.open(false).first
2229 issue = Issue.open(false).first
2230 was_closed_on = issue.closed_on
2230 was_closed_on = issue.closed_on
2231 assert_not_nil was_closed_on
2231 assert_not_nil was_closed_on
2232 issue.subject = 'Reopening a closed issue'
2232 issue.subject = 'Reopening a closed issue'
2233 issue.status_id = 1
2233 issue.status_id = 1
2234 issue.save!
2234 issue.save!
2235 issue.reload
2235 issue.reload
2236 assert !issue.closed?
2236 assert !issue.closed?
2237 assert_equal was_closed_on, issue.closed_on
2237 assert_equal was_closed_on, issue.closed_on
2238 end
2238 end
2239
2239
2240 def test_status_was_should_return_nil_for_new_issue
2240 def test_status_was_should_return_nil_for_new_issue
2241 issue = Issue.new
2241 issue = Issue.new
2242 assert_nil issue.status_was
2242 assert_nil issue.status_was
2243 end
2243 end
2244
2244
2245 def test_status_was_should_return_status_before_change
2245 def test_status_was_should_return_status_before_change
2246 issue = Issue.find(1)
2246 issue = Issue.find(1)
2247 issue.status = IssueStatus.find(2)
2247 issue.status = IssueStatus.find(2)
2248 assert_equal IssueStatus.find(1), issue.status_was
2248 assert_equal IssueStatus.find(1), issue.status_was
2249 end
2249 end
2250
2250
2251 def test_status_was_should_be_reset_on_save
2251 def test_status_was_should_be_reset_on_save
2252 issue = Issue.find(1)
2252 issue = Issue.find(1)
2253 issue.status = IssueStatus.find(2)
2253 issue.status = IssueStatus.find(2)
2254 assert_equal IssueStatus.find(1), issue.status_was
2254 assert_equal IssueStatus.find(1), issue.status_was
2255 assert issue.save!
2255 assert issue.save!
2256 assert_equal IssueStatus.find(2), issue.status_was
2256 assert_equal IssueStatus.find(2), issue.status_was
2257 end
2257 end
2258 end
2258 end
General Comments 0
You need to be logged in to leave comments. Login now