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