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