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