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