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