##// END OF EJS Templates
code layout clean up test_rescheduling_an_issue_should_reschedule_following_issue of unit issue test...
Toshi MARUYAMA -
r10421:dd887891f7ea
parent child
Show More
@@ -1,1686 +1,1693
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class IssueTest < ActiveSupport::TestCase
20 class IssueTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :members, :member_roles, :roles,
21 fixtures :projects, :users, :members, :member_roles, :roles,
22 :groups_users,
22 :groups_users,
23 :trackers, :projects_trackers,
23 :trackers, :projects_trackers,
24 :enabled_modules,
24 :enabled_modules,
25 :versions,
25 :versions,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
27 :enumerations,
27 :enumerations,
28 :issues, :journals, :journal_details,
28 :issues, :journals, :journal_details,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
30 :time_entries
30 :time_entries
31
31
32 include Redmine::I18n
32 include Redmine::I18n
33
33
34 def teardown
34 def teardown
35 User.current = nil
35 User.current = nil
36 end
36 end
37
37
38 def test_create
38 def test_create
39 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
39 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
40 :status_id => 1, :priority => IssuePriority.all.first,
40 :status_id => 1, :priority => IssuePriority.all.first,
41 :subject => 'test_create',
41 :subject => 'test_create',
42 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
42 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
43 assert issue.save
43 assert issue.save
44 issue.reload
44 issue.reload
45 assert_equal 1.5, issue.estimated_hours
45 assert_equal 1.5, issue.estimated_hours
46 end
46 end
47
47
48 def test_create_minimal
48 def test_create_minimal
49 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
49 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
50 :status_id => 1, :priority => IssuePriority.all.first,
50 :status_id => 1, :priority => IssuePriority.all.first,
51 :subject => 'test_create')
51 :subject => 'test_create')
52 assert issue.save
52 assert issue.save
53 assert issue.description.nil?
53 assert issue.description.nil?
54 assert_nil issue.estimated_hours
54 assert_nil issue.estimated_hours
55 end
55 end
56
56
57 def test_create_with_required_custom_field
57 def test_create_with_required_custom_field
58 set_language_if_valid 'en'
58 set_language_if_valid 'en'
59 field = IssueCustomField.find_by_name('Database')
59 field = IssueCustomField.find_by_name('Database')
60 field.update_attribute(:is_required, true)
60 field.update_attribute(:is_required, true)
61
61
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
63 :status_id => 1, :subject => 'test_create',
63 :status_id => 1, :subject => 'test_create',
64 :description => 'IssueTest#test_create_with_required_custom_field')
64 :description => 'IssueTest#test_create_with_required_custom_field')
65 assert issue.available_custom_fields.include?(field)
65 assert issue.available_custom_fields.include?(field)
66 # No value for the custom field
66 # No value for the custom field
67 assert !issue.save
67 assert !issue.save
68 assert_equal ["Database can't be blank"], issue.errors.full_messages
68 assert_equal ["Database can't be blank"], issue.errors.full_messages
69 # Blank value
69 # Blank value
70 issue.custom_field_values = { field.id => '' }
70 issue.custom_field_values = { field.id => '' }
71 assert !issue.save
71 assert !issue.save
72 assert_equal ["Database can't be blank"], issue.errors.full_messages
72 assert_equal ["Database can't be blank"], issue.errors.full_messages
73 # Invalid value
73 # Invalid value
74 issue.custom_field_values = { field.id => 'SQLServer' }
74 issue.custom_field_values = { field.id => 'SQLServer' }
75 assert !issue.save
75 assert !issue.save
76 assert_equal ["Database is not included in the list"], issue.errors.full_messages
76 assert_equal ["Database is not included in the list"], issue.errors.full_messages
77 # Valid value
77 # Valid value
78 issue.custom_field_values = { field.id => 'PostgreSQL' }
78 issue.custom_field_values = { field.id => 'PostgreSQL' }
79 assert issue.save
79 assert issue.save
80 issue.reload
80 issue.reload
81 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
81 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
82 end
82 end
83
83
84 def test_create_with_group_assignment
84 def test_create_with_group_assignment
85 with_settings :issue_group_assignment => '1' do
85 with_settings :issue_group_assignment => '1' do
86 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
86 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
87 :subject => 'Group assignment',
87 :subject => 'Group assignment',
88 :assigned_to_id => 11).save
88 :assigned_to_id => 11).save
89 issue = Issue.first(:order => 'id DESC')
89 issue = Issue.first(:order => 'id DESC')
90 assert_kind_of Group, issue.assigned_to
90 assert_kind_of Group, issue.assigned_to
91 assert_equal Group.find(11), issue.assigned_to
91 assert_equal Group.find(11), issue.assigned_to
92 end
92 end
93 end
93 end
94
94
95 def test_create_with_parent_issue_id
95 def test_create_with_parent_issue_id
96 issue = Issue.new(:project_id => 1, :tracker_id => 1,
96 issue = Issue.new(:project_id => 1, :tracker_id => 1,
97 :author_id => 1, :subject => 'Group assignment',
97 :author_id => 1, :subject => 'Group assignment',
98 :parent_issue_id => 1)
98 :parent_issue_id => 1)
99 assert_save issue
99 assert_save issue
100 assert_equal 1, issue.parent_issue_id
100 assert_equal 1, issue.parent_issue_id
101 assert_equal Issue.find(1), issue.parent
101 assert_equal Issue.find(1), issue.parent
102 end
102 end
103
103
104 def test_create_with_sharp_parent_issue_id
104 def test_create_with_sharp_parent_issue_id
105 issue = Issue.new(:project_id => 1, :tracker_id => 1,
105 issue = Issue.new(:project_id => 1, :tracker_id => 1,
106 :author_id => 1, :subject => 'Group assignment',
106 :author_id => 1, :subject => 'Group assignment',
107 :parent_issue_id => "#1")
107 :parent_issue_id => "#1")
108 assert_save issue
108 assert_save issue
109 assert_equal 1, issue.parent_issue_id
109 assert_equal 1, issue.parent_issue_id
110 assert_equal Issue.find(1), issue.parent
110 assert_equal Issue.find(1), issue.parent
111 end
111 end
112
112
113 def test_create_with_invalid_parent_issue_id
113 def test_create_with_invalid_parent_issue_id
114 set_language_if_valid 'en'
114 set_language_if_valid 'en'
115 issue = Issue.new(:project_id => 1, :tracker_id => 1,
115 issue = Issue.new(:project_id => 1, :tracker_id => 1,
116 :author_id => 1, :subject => 'Group assignment',
116 :author_id => 1, :subject => 'Group assignment',
117 :parent_issue_id => '01ABC')
117 :parent_issue_id => '01ABC')
118 assert !issue.save
118 assert !issue.save
119 assert_equal '01ABC', issue.parent_issue_id
119 assert_equal '01ABC', issue.parent_issue_id
120 assert_include 'Parent task is invalid', issue.errors.full_messages
120 assert_include 'Parent task is invalid', issue.errors.full_messages
121 end
121 end
122
122
123 def test_create_with_invalid_sharp_parent_issue_id
123 def test_create_with_invalid_sharp_parent_issue_id
124 set_language_if_valid 'en'
124 set_language_if_valid 'en'
125 issue = Issue.new(:project_id => 1, :tracker_id => 1,
125 issue = Issue.new(:project_id => 1, :tracker_id => 1,
126 :author_id => 1, :subject => 'Group assignment',
126 :author_id => 1, :subject => 'Group assignment',
127 :parent_issue_id => '#01ABC')
127 :parent_issue_id => '#01ABC')
128 assert !issue.save
128 assert !issue.save
129 assert_equal '#01ABC', issue.parent_issue_id
129 assert_equal '#01ABC', issue.parent_issue_id
130 assert_include 'Parent task is invalid', issue.errors.full_messages
130 assert_include 'Parent task is invalid', issue.errors.full_messages
131 end
131 end
132
132
133 def assert_visibility_match(user, issues)
133 def assert_visibility_match(user, issues)
134 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
134 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
135 end
135 end
136
136
137 def test_visible_scope_for_anonymous
137 def test_visible_scope_for_anonymous
138 # Anonymous user should see issues of public projects only
138 # Anonymous user should see issues of public projects only
139 issues = Issue.visible(User.anonymous).all
139 issues = Issue.visible(User.anonymous).all
140 assert issues.any?
140 assert issues.any?
141 assert_nil issues.detect {|issue| !issue.project.is_public?}
141 assert_nil issues.detect {|issue| !issue.project.is_public?}
142 assert_nil issues.detect {|issue| issue.is_private?}
142 assert_nil issues.detect {|issue| issue.is_private?}
143 assert_visibility_match User.anonymous, issues
143 assert_visibility_match User.anonymous, issues
144 end
144 end
145
145
146 def test_visible_scope_for_anonymous_without_view_issues_permissions
146 def test_visible_scope_for_anonymous_without_view_issues_permissions
147 # Anonymous user should not see issues without permission
147 # Anonymous user should not see issues without permission
148 Role.anonymous.remove_permission!(:view_issues)
148 Role.anonymous.remove_permission!(:view_issues)
149 issues = Issue.visible(User.anonymous).all
149 issues = Issue.visible(User.anonymous).all
150 assert issues.empty?
150 assert issues.empty?
151 assert_visibility_match User.anonymous, issues
151 assert_visibility_match User.anonymous, issues
152 end
152 end
153
153
154 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
154 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
155 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
155 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
156 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
156 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
157 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
157 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
158 assert !issue.visible?(User.anonymous)
158 assert !issue.visible?(User.anonymous)
159 end
159 end
160
160
161 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
161 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
162 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
162 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
163 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
163 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
164 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
164 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
165 assert !issue.visible?(User.anonymous)
165 assert !issue.visible?(User.anonymous)
166 end
166 end
167
167
168 def test_visible_scope_for_non_member
168 def test_visible_scope_for_non_member
169 user = User.find(9)
169 user = User.find(9)
170 assert user.projects.empty?
170 assert user.projects.empty?
171 # Non member user should see issues of public projects only
171 # Non member user should see issues of public projects only
172 issues = Issue.visible(user).all
172 issues = Issue.visible(user).all
173 assert issues.any?
173 assert issues.any?
174 assert_nil issues.detect {|issue| !issue.project.is_public?}
174 assert_nil issues.detect {|issue| !issue.project.is_public?}
175 assert_nil issues.detect {|issue| issue.is_private?}
175 assert_nil issues.detect {|issue| issue.is_private?}
176 assert_visibility_match user, issues
176 assert_visibility_match user, issues
177 end
177 end
178
178
179 def test_visible_scope_for_non_member_with_own_issues_visibility
179 def test_visible_scope_for_non_member_with_own_issues_visibility
180 Role.non_member.update_attribute :issues_visibility, 'own'
180 Role.non_member.update_attribute :issues_visibility, 'own'
181 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
181 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
182 user = User.find(9)
182 user = User.find(9)
183
183
184 issues = Issue.visible(user).all
184 issues = Issue.visible(user).all
185 assert issues.any?
185 assert issues.any?
186 assert_nil issues.detect {|issue| issue.author != user}
186 assert_nil issues.detect {|issue| issue.author != user}
187 assert_visibility_match user, issues
187 assert_visibility_match user, issues
188 end
188 end
189
189
190 def test_visible_scope_for_non_member_without_view_issues_permissions
190 def test_visible_scope_for_non_member_without_view_issues_permissions
191 # Non member user should not see issues without permission
191 # Non member user should not see issues without permission
192 Role.non_member.remove_permission!(:view_issues)
192 Role.non_member.remove_permission!(:view_issues)
193 user = User.find(9)
193 user = User.find(9)
194 assert user.projects.empty?
194 assert user.projects.empty?
195 issues = Issue.visible(user).all
195 issues = Issue.visible(user).all
196 assert issues.empty?
196 assert issues.empty?
197 assert_visibility_match user, issues
197 assert_visibility_match user, issues
198 end
198 end
199
199
200 def test_visible_scope_for_member
200 def test_visible_scope_for_member
201 user = User.find(9)
201 user = User.find(9)
202 # User should see issues of projects for which he has view_issues permissions only
202 # User should see issues of projects for which he has view_issues permissions only
203 Role.non_member.remove_permission!(:view_issues)
203 Role.non_member.remove_permission!(:view_issues)
204 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
204 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
205 issues = Issue.visible(user).all
205 issues = Issue.visible(user).all
206 assert issues.any?
206 assert issues.any?
207 assert_nil issues.detect {|issue| issue.project_id != 3}
207 assert_nil issues.detect {|issue| issue.project_id != 3}
208 assert_nil issues.detect {|issue| issue.is_private?}
208 assert_nil issues.detect {|issue| issue.is_private?}
209 assert_visibility_match user, issues
209 assert_visibility_match user, issues
210 end
210 end
211
211
212 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
212 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
213 user = User.find(8)
213 user = User.find(8)
214 assert user.groups.any?
214 assert user.groups.any?
215 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
215 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
216 Role.non_member.remove_permission!(:view_issues)
216 Role.non_member.remove_permission!(:view_issues)
217
217
218 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
218 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
219 :status_id => 1, :priority => IssuePriority.all.first,
219 :status_id => 1, :priority => IssuePriority.all.first,
220 :subject => 'Assignment test',
220 :subject => 'Assignment test',
221 :assigned_to => user.groups.first,
221 :assigned_to => user.groups.first,
222 :is_private => true)
222 :is_private => true)
223
223
224 Role.find(2).update_attribute :issues_visibility, 'default'
224 Role.find(2).update_attribute :issues_visibility, 'default'
225 issues = Issue.visible(User.find(8)).all
225 issues = Issue.visible(User.find(8)).all
226 assert issues.any?
226 assert issues.any?
227 assert issues.include?(issue)
227 assert issues.include?(issue)
228
228
229 Role.find(2).update_attribute :issues_visibility, 'own'
229 Role.find(2).update_attribute :issues_visibility, 'own'
230 issues = Issue.visible(User.find(8)).all
230 issues = Issue.visible(User.find(8)).all
231 assert issues.any?
231 assert issues.any?
232 assert issues.include?(issue)
232 assert issues.include?(issue)
233 end
233 end
234
234
235 def test_visible_scope_for_admin
235 def test_visible_scope_for_admin
236 user = User.find(1)
236 user = User.find(1)
237 user.members.each(&:destroy)
237 user.members.each(&:destroy)
238 assert user.projects.empty?
238 assert user.projects.empty?
239 issues = Issue.visible(user).all
239 issues = Issue.visible(user).all
240 assert issues.any?
240 assert issues.any?
241 # Admin should see issues on private projects that he does not belong to
241 # Admin should see issues on private projects that he does not belong to
242 assert issues.detect {|issue| !issue.project.is_public?}
242 assert issues.detect {|issue| !issue.project.is_public?}
243 # Admin should see private issues of other users
243 # Admin should see private issues of other users
244 assert issues.detect {|issue| issue.is_private? && issue.author != user}
244 assert issues.detect {|issue| issue.is_private? && issue.author != user}
245 assert_visibility_match user, issues
245 assert_visibility_match user, issues
246 end
246 end
247
247
248 def test_visible_scope_with_project
248 def test_visible_scope_with_project
249 project = Project.find(1)
249 project = Project.find(1)
250 issues = Issue.visible(User.find(2), :project => project).all
250 issues = Issue.visible(User.find(2), :project => project).all
251 projects = issues.collect(&:project).uniq
251 projects = issues.collect(&:project).uniq
252 assert_equal 1, projects.size
252 assert_equal 1, projects.size
253 assert_equal project, projects.first
253 assert_equal project, projects.first
254 end
254 end
255
255
256 def test_visible_scope_with_project_and_subprojects
256 def test_visible_scope_with_project_and_subprojects
257 project = Project.find(1)
257 project = Project.find(1)
258 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
258 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
259 projects = issues.collect(&:project).uniq
259 projects = issues.collect(&:project).uniq
260 assert projects.size > 1
260 assert projects.size > 1
261 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
261 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
262 end
262 end
263
263
264 def test_visible_and_nested_set_scopes
264 def test_visible_and_nested_set_scopes
265 assert_equal 0, Issue.find(1).descendants.visible.all.size
265 assert_equal 0, Issue.find(1).descendants.visible.all.size
266 end
266 end
267
267
268 def test_open_scope
268 def test_open_scope
269 issues = Issue.open.all
269 issues = Issue.open.all
270 assert_nil issues.detect(&:closed?)
270 assert_nil issues.detect(&:closed?)
271 end
271 end
272
272
273 def test_open_scope_with_arg
273 def test_open_scope_with_arg
274 issues = Issue.open(false).all
274 issues = Issue.open(false).all
275 assert_equal issues, issues.select(&:closed?)
275 assert_equal issues, issues.select(&:closed?)
276 end
276 end
277
277
278 def test_errors_full_messages_should_include_custom_fields_errors
278 def test_errors_full_messages_should_include_custom_fields_errors
279 field = IssueCustomField.find_by_name('Database')
279 field = IssueCustomField.find_by_name('Database')
280
280
281 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
281 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
282 :status_id => 1, :subject => 'test_create',
282 :status_id => 1, :subject => 'test_create',
283 :description => 'IssueTest#test_create_with_required_custom_field')
283 :description => 'IssueTest#test_create_with_required_custom_field')
284 assert issue.available_custom_fields.include?(field)
284 assert issue.available_custom_fields.include?(field)
285 # Invalid value
285 # Invalid value
286 issue.custom_field_values = { field.id => 'SQLServer' }
286 issue.custom_field_values = { field.id => 'SQLServer' }
287
287
288 assert !issue.valid?
288 assert !issue.valid?
289 assert_equal 1, issue.errors.full_messages.size
289 assert_equal 1, issue.errors.full_messages.size
290 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
290 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
291 issue.errors.full_messages.first
291 issue.errors.full_messages.first
292 end
292 end
293
293
294 def test_update_issue_with_required_custom_field
294 def test_update_issue_with_required_custom_field
295 field = IssueCustomField.find_by_name('Database')
295 field = IssueCustomField.find_by_name('Database')
296 field.update_attribute(:is_required, true)
296 field.update_attribute(:is_required, true)
297
297
298 issue = Issue.find(1)
298 issue = Issue.find(1)
299 assert_nil issue.custom_value_for(field)
299 assert_nil issue.custom_value_for(field)
300 assert issue.available_custom_fields.include?(field)
300 assert issue.available_custom_fields.include?(field)
301 # No change to custom values, issue can be saved
301 # No change to custom values, issue can be saved
302 assert issue.save
302 assert issue.save
303 # Blank value
303 # Blank value
304 issue.custom_field_values = { field.id => '' }
304 issue.custom_field_values = { field.id => '' }
305 assert !issue.save
305 assert !issue.save
306 # Valid value
306 # Valid value
307 issue.custom_field_values = { field.id => 'PostgreSQL' }
307 issue.custom_field_values = { field.id => 'PostgreSQL' }
308 assert issue.save
308 assert issue.save
309 issue.reload
309 issue.reload
310 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
310 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
311 end
311 end
312
312
313 def test_should_not_update_attributes_if_custom_fields_validation_fails
313 def test_should_not_update_attributes_if_custom_fields_validation_fails
314 issue = Issue.find(1)
314 issue = Issue.find(1)
315 field = IssueCustomField.find_by_name('Database')
315 field = IssueCustomField.find_by_name('Database')
316 assert issue.available_custom_fields.include?(field)
316 assert issue.available_custom_fields.include?(field)
317
317
318 issue.custom_field_values = { field.id => 'Invalid' }
318 issue.custom_field_values = { field.id => 'Invalid' }
319 issue.subject = 'Should be not be saved'
319 issue.subject = 'Should be not be saved'
320 assert !issue.save
320 assert !issue.save
321
321
322 issue.reload
322 issue.reload
323 assert_equal "Can't print recipes", issue.subject
323 assert_equal "Can't print recipes", issue.subject
324 end
324 end
325
325
326 def test_should_not_recreate_custom_values_objects_on_update
326 def test_should_not_recreate_custom_values_objects_on_update
327 field = IssueCustomField.find_by_name('Database')
327 field = IssueCustomField.find_by_name('Database')
328
328
329 issue = Issue.find(1)
329 issue = Issue.find(1)
330 issue.custom_field_values = { field.id => 'PostgreSQL' }
330 issue.custom_field_values = { field.id => 'PostgreSQL' }
331 assert issue.save
331 assert issue.save
332 custom_value = issue.custom_value_for(field)
332 custom_value = issue.custom_value_for(field)
333 issue.reload
333 issue.reload
334 issue.custom_field_values = { field.id => 'MySQL' }
334 issue.custom_field_values = { field.id => 'MySQL' }
335 assert issue.save
335 assert issue.save
336 issue.reload
336 issue.reload
337 assert_equal custom_value.id, issue.custom_value_for(field).id
337 assert_equal custom_value.id, issue.custom_value_for(field).id
338 end
338 end
339
339
340 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
340 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
341 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'Test', :custom_field_values => {'2' => 'Test'})
341 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'Test', :custom_field_values => {'2' => 'Test'})
342 assert !Tracker.find(2).custom_field_ids.include?(2)
342 assert !Tracker.find(2).custom_field_ids.include?(2)
343
343
344 issue = Issue.find(issue.id)
344 issue = Issue.find(issue.id)
345 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
345 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
346
346
347 issue = Issue.find(issue.id)
347 issue = Issue.find(issue.id)
348 custom_value = issue.custom_value_for(2)
348 custom_value = issue.custom_value_for(2)
349 assert_not_nil custom_value
349 assert_not_nil custom_value
350 assert_equal 'Test', custom_value.value
350 assert_equal 'Test', custom_value.value
351 end
351 end
352
352
353 def test_assigning_tracker_id_should_reload_custom_fields_values
353 def test_assigning_tracker_id_should_reload_custom_fields_values
354 issue = Issue.new(:project => Project.find(1))
354 issue = Issue.new(:project => Project.find(1))
355 assert issue.custom_field_values.empty?
355 assert issue.custom_field_values.empty?
356 issue.tracker_id = 1
356 issue.tracker_id = 1
357 assert issue.custom_field_values.any?
357 assert issue.custom_field_values.any?
358 end
358 end
359
359
360 def test_assigning_attributes_should_assign_project_and_tracker_first
360 def test_assigning_attributes_should_assign_project_and_tracker_first
361 seq = sequence('seq')
361 seq = sequence('seq')
362 issue = Issue.new
362 issue = Issue.new
363 issue.expects(:project_id=).in_sequence(seq)
363 issue.expects(:project_id=).in_sequence(seq)
364 issue.expects(:tracker_id=).in_sequence(seq)
364 issue.expects(:tracker_id=).in_sequence(seq)
365 issue.expects(:subject=).in_sequence(seq)
365 issue.expects(:subject=).in_sequence(seq)
366 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
366 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
367 end
367 end
368
368
369 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
369 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
370 attributes = ActiveSupport::OrderedHash.new
370 attributes = ActiveSupport::OrderedHash.new
371 attributes['custom_field_values'] = { '1' => 'MySQL' }
371 attributes['custom_field_values'] = { '1' => 'MySQL' }
372 attributes['tracker_id'] = '1'
372 attributes['tracker_id'] = '1'
373 issue = Issue.new(:project => Project.find(1))
373 issue = Issue.new(:project => Project.find(1))
374 issue.attributes = attributes
374 issue.attributes = attributes
375 assert_equal 'MySQL', issue.custom_field_value(1)
375 assert_equal 'MySQL', issue.custom_field_value(1)
376 end
376 end
377
377
378 def test_should_update_issue_with_disabled_tracker
378 def test_should_update_issue_with_disabled_tracker
379 p = Project.find(1)
379 p = Project.find(1)
380 issue = Issue.find(1)
380 issue = Issue.find(1)
381
381
382 p.trackers.delete(issue.tracker)
382 p.trackers.delete(issue.tracker)
383 assert !p.trackers.include?(issue.tracker)
383 assert !p.trackers.include?(issue.tracker)
384
384
385 issue.reload
385 issue.reload
386 issue.subject = 'New subject'
386 issue.subject = 'New subject'
387 assert issue.save
387 assert issue.save
388 end
388 end
389
389
390 def test_should_not_set_a_disabled_tracker
390 def test_should_not_set_a_disabled_tracker
391 p = Project.find(1)
391 p = Project.find(1)
392 p.trackers.delete(Tracker.find(2))
392 p.trackers.delete(Tracker.find(2))
393
393
394 issue = Issue.find(1)
394 issue = Issue.find(1)
395 issue.tracker_id = 2
395 issue.tracker_id = 2
396 issue.subject = 'New subject'
396 issue.subject = 'New subject'
397 assert !issue.save
397 assert !issue.save
398 assert_not_nil issue.errors[:tracker_id]
398 assert_not_nil issue.errors[:tracker_id]
399 end
399 end
400
400
401 def test_category_based_assignment
401 def test_category_based_assignment
402 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
402 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
403 :status_id => 1, :priority => IssuePriority.all.first,
403 :status_id => 1, :priority => IssuePriority.all.first,
404 :subject => 'Assignment test',
404 :subject => 'Assignment test',
405 :description => 'Assignment test', :category_id => 1)
405 :description => 'Assignment test', :category_id => 1)
406 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
406 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
407 end
407 end
408
408
409 def test_new_statuses_allowed_to
409 def test_new_statuses_allowed_to
410 WorkflowTransition.delete_all
410 WorkflowTransition.delete_all
411
411
412 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
412 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
413 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
413 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
414 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
414 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
415 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
415 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
416 status = IssueStatus.find(1)
416 status = IssueStatus.find(1)
417 role = Role.find(1)
417 role = Role.find(1)
418 tracker = Tracker.find(1)
418 tracker = Tracker.find(1)
419 user = User.find(2)
419 user = User.find(2)
420
420
421 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author_id => 1)
421 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author_id => 1)
422 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
422 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
423
423
424 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
424 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
425 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
425 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
426
426
427 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author_id => 1, :assigned_to => user)
427 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author_id => 1, :assigned_to => user)
428 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
428 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
429
429
430 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
430 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
431 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
431 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
432 end
432 end
433
433
434 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
434 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
435 admin = User.find(1)
435 admin = User.find(1)
436 issue = Issue.find(1)
436 issue = Issue.find(1)
437 assert !admin.member_of?(issue.project)
437 assert !admin.member_of?(issue.project)
438 expected_statuses = [issue.status] + WorkflowTransition.find_all_by_old_status_id(issue.status_id).map(&:new_status).uniq.sort
438 expected_statuses = [issue.status] + WorkflowTransition.find_all_by_old_status_id(issue.status_id).map(&:new_status).uniq.sort
439
439
440 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
440 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
441 end
441 end
442
442
443 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
443 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
444 issue = Issue.find(1).copy
444 issue = Issue.find(1).copy
445 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
445 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
446
446
447 issue = Issue.find(2).copy
447 issue = Issue.find(2).copy
448 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
448 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
449 end
449 end
450
450
451 def test_safe_attributes_names_should_not_include_disabled_field
451 def test_safe_attributes_names_should_not_include_disabled_field
452 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
452 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
453
453
454 issue = Issue.new(:tracker => tracker)
454 issue = Issue.new(:tracker => tracker)
455 assert_include 'tracker_id', issue.safe_attribute_names
455 assert_include 'tracker_id', issue.safe_attribute_names
456 assert_include 'status_id', issue.safe_attribute_names
456 assert_include 'status_id', issue.safe_attribute_names
457 assert_include 'subject', issue.safe_attribute_names
457 assert_include 'subject', issue.safe_attribute_names
458 assert_include 'description', issue.safe_attribute_names
458 assert_include 'description', issue.safe_attribute_names
459 assert_include 'custom_field_values', issue.safe_attribute_names
459 assert_include 'custom_field_values', issue.safe_attribute_names
460 assert_include 'custom_fields', issue.safe_attribute_names
460 assert_include 'custom_fields', issue.safe_attribute_names
461 assert_include 'lock_version', issue.safe_attribute_names
461 assert_include 'lock_version', issue.safe_attribute_names
462
462
463 tracker.core_fields.each do |field|
463 tracker.core_fields.each do |field|
464 assert_include field, issue.safe_attribute_names
464 assert_include field, issue.safe_attribute_names
465 end
465 end
466
466
467 tracker.disabled_core_fields.each do |field|
467 tracker.disabled_core_fields.each do |field|
468 assert_not_include field, issue.safe_attribute_names
468 assert_not_include field, issue.safe_attribute_names
469 end
469 end
470 end
470 end
471
471
472 def test_safe_attributes_should_ignore_disabled_fields
472 def test_safe_attributes_should_ignore_disabled_fields
473 tracker = Tracker.find(1)
473 tracker = Tracker.find(1)
474 tracker.core_fields = %w(assigned_to_id due_date)
474 tracker.core_fields = %w(assigned_to_id due_date)
475 tracker.save!
475 tracker.save!
476
476
477 issue = Issue.new(:tracker => tracker)
477 issue = Issue.new(:tracker => tracker)
478 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
478 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
479 assert_nil issue.start_date
479 assert_nil issue.start_date
480 assert_equal Date.parse('2012-07-14'), issue.due_date
480 assert_equal Date.parse('2012-07-14'), issue.due_date
481 end
481 end
482
482
483 def test_safe_attributes_should_accept_target_tracker_enabled_fields
483 def test_safe_attributes_should_accept_target_tracker_enabled_fields
484 source = Tracker.find(1)
484 source = Tracker.find(1)
485 source.core_fields = []
485 source.core_fields = []
486 source.save!
486 source.save!
487 target = Tracker.find(2)
487 target = Tracker.find(2)
488 target.core_fields = %w(assigned_to_id due_date)
488 target.core_fields = %w(assigned_to_id due_date)
489 target.save!
489 target.save!
490
490
491 issue = Issue.new(:tracker => source)
491 issue = Issue.new(:tracker => source)
492 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
492 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
493 assert_equal target, issue.tracker
493 assert_equal target, issue.tracker
494 assert_equal Date.parse('2012-07-14'), issue.due_date
494 assert_equal Date.parse('2012-07-14'), issue.due_date
495 end
495 end
496
496
497 def test_safe_attributes_should_not_include_readonly_fields
497 def test_safe_attributes_should_not_include_readonly_fields
498 WorkflowPermission.delete_all
498 WorkflowPermission.delete_all
499 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
499 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
500 user = User.find(2)
500 user = User.find(2)
501
501
502 issue = Issue.new(:project_id => 1, :tracker_id => 1)
502 issue = Issue.new(:project_id => 1, :tracker_id => 1)
503 assert_equal %w(due_date), issue.read_only_attribute_names(user)
503 assert_equal %w(due_date), issue.read_only_attribute_names(user)
504 assert_not_include 'due_date', issue.safe_attribute_names(user)
504 assert_not_include 'due_date', issue.safe_attribute_names(user)
505
505
506 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
506 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
507 assert_equal Date.parse('2012-07-14'), issue.start_date
507 assert_equal Date.parse('2012-07-14'), issue.start_date
508 assert_nil issue.due_date
508 assert_nil issue.due_date
509 end
509 end
510
510
511 def test_safe_attributes_should_not_include_readonly_custom_fields
511 def test_safe_attributes_should_not_include_readonly_custom_fields
512 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1])
512 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1])
513 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1])
513 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1])
514
514
515 WorkflowPermission.delete_all
515 WorkflowPermission.delete_all
516 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
516 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
517 user = User.find(2)
517 user = User.find(2)
518
518
519 issue = Issue.new(:project_id => 1, :tracker_id => 1)
519 issue = Issue.new(:project_id => 1, :tracker_id => 1)
520 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
520 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
521 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
521 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
522
522
523 issue.send :safe_attributes=, {'custom_field_values' => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}}, user
523 issue.send :safe_attributes=, {'custom_field_values' => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}}, user
524 assert_equal 'value1', issue.custom_field_value(cf1)
524 assert_equal 'value1', issue.custom_field_value(cf1)
525 assert_nil issue.custom_field_value(cf2)
525 assert_nil issue.custom_field_value(cf2)
526
526
527 issue.send :safe_attributes=, {'custom_fields' => [{'id' => cf1.id.to_s, 'value' => 'valuea'}, {'id' => cf2.id.to_s, 'value' => 'valueb'}]}, user
527 issue.send :safe_attributes=, {'custom_fields' => [{'id' => cf1.id.to_s, 'value' => 'valuea'}, {'id' => cf2.id.to_s, 'value' => 'valueb'}]}, user
528 assert_equal 'valuea', issue.custom_field_value(cf1)
528 assert_equal 'valuea', issue.custom_field_value(cf1)
529 assert_nil issue.custom_field_value(cf2)
529 assert_nil issue.custom_field_value(cf2)
530 end
530 end
531
531
532 def test_editable_custom_field_values_should_return_non_readonly_custom_values
532 def test_editable_custom_field_values_should_return_non_readonly_custom_values
533 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
533 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
534 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
534 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
535
535
536 WorkflowPermission.delete_all
536 WorkflowPermission.delete_all
537 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
537 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
538 user = User.find(2)
538 user = User.find(2)
539
539
540 issue = Issue.new(:project_id => 1, :tracker_id => 1)
540 issue = Issue.new(:project_id => 1, :tracker_id => 1)
541 values = issue.editable_custom_field_values(user)
541 values = issue.editable_custom_field_values(user)
542 assert values.detect {|value| value.custom_field == cf1}
542 assert values.detect {|value| value.custom_field == cf1}
543 assert_nil values.detect {|value| value.custom_field == cf2}
543 assert_nil values.detect {|value| value.custom_field == cf2}
544
544
545 issue.tracker_id = 2
545 issue.tracker_id = 2
546 values = issue.editable_custom_field_values(user)
546 values = issue.editable_custom_field_values(user)
547 assert values.detect {|value| value.custom_field == cf1}
547 assert values.detect {|value| value.custom_field == cf1}
548 assert values.detect {|value| value.custom_field == cf2}
548 assert values.detect {|value| value.custom_field == cf2}
549 end
549 end
550
550
551 def test_safe_attributes_should_accept_target_tracker_writable_fields
551 def test_safe_attributes_should_accept_target_tracker_writable_fields
552 WorkflowPermission.delete_all
552 WorkflowPermission.delete_all
553 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
553 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
554 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
554 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
555 user = User.find(2)
555 user = User.find(2)
556
556
557 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
557 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
558
558
559 issue.send :safe_attributes=, {'start_date' => '2012-07-12', 'due_date' => '2012-07-14'}, user
559 issue.send :safe_attributes=, {'start_date' => '2012-07-12', 'due_date' => '2012-07-14'}, user
560 assert_equal Date.parse('2012-07-12'), issue.start_date
560 assert_equal Date.parse('2012-07-12'), issue.start_date
561 assert_nil issue.due_date
561 assert_nil issue.due_date
562
562
563 issue.send :safe_attributes=, {'start_date' => '2012-07-15', 'due_date' => '2012-07-16', 'tracker_id' => 2}, user
563 issue.send :safe_attributes=, {'start_date' => '2012-07-15', 'due_date' => '2012-07-16', 'tracker_id' => 2}, user
564 assert_equal Date.parse('2012-07-12'), issue.start_date
564 assert_equal Date.parse('2012-07-12'), issue.start_date
565 assert_equal Date.parse('2012-07-16'), issue.due_date
565 assert_equal Date.parse('2012-07-16'), issue.due_date
566 end
566 end
567
567
568 def test_safe_attributes_should_accept_target_status_writable_fields
568 def test_safe_attributes_should_accept_target_status_writable_fields
569 WorkflowPermission.delete_all
569 WorkflowPermission.delete_all
570 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
570 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
571 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
571 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
572 user = User.find(2)
572 user = User.find(2)
573
573
574 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
574 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
575
575
576 issue.send :safe_attributes=, {'start_date' => '2012-07-12', 'due_date' => '2012-07-14'}, user
576 issue.send :safe_attributes=, {'start_date' => '2012-07-12', 'due_date' => '2012-07-14'}, user
577 assert_equal Date.parse('2012-07-12'), issue.start_date
577 assert_equal Date.parse('2012-07-12'), issue.start_date
578 assert_nil issue.due_date
578 assert_nil issue.due_date
579
579
580 issue.send :safe_attributes=, {'start_date' => '2012-07-15', 'due_date' => '2012-07-16', 'status_id' => 2}, user
580 issue.send :safe_attributes=, {'start_date' => '2012-07-15', 'due_date' => '2012-07-16', 'status_id' => 2}, user
581 assert_equal Date.parse('2012-07-12'), issue.start_date
581 assert_equal Date.parse('2012-07-12'), issue.start_date
582 assert_equal Date.parse('2012-07-16'), issue.due_date
582 assert_equal Date.parse('2012-07-16'), issue.due_date
583 end
583 end
584
584
585 def test_required_attributes_should_be_validated
585 def test_required_attributes_should_be_validated
586 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
586 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
587
587
588 WorkflowPermission.delete_all
588 WorkflowPermission.delete_all
589 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
589 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
590 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'category_id', :rule => 'required')
590 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'category_id', :rule => 'required')
591 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf.id.to_s, :rule => 'required')
591 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf.id.to_s, :rule => 'required')
592
592
593 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'start_date', :rule => 'required')
593 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'start_date', :rule => 'required')
594 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf.id.to_s, :rule => 'required')
594 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf.id.to_s, :rule => 'required')
595 user = User.find(2)
595 user = User.find(2)
596
596
597 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Required fields', :author => user)
597 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Required fields', :author => user)
598 assert_equal [cf.id.to_s, "category_id", "due_date"], issue.required_attribute_names(user).sort
598 assert_equal [cf.id.to_s, "category_id", "due_date"], issue.required_attribute_names(user).sort
599 assert !issue.save, "Issue was saved"
599 assert !issue.save, "Issue was saved"
600 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"], issue.errors.full_messages.sort
600 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"], issue.errors.full_messages.sort
601
601
602 issue.tracker_id = 2
602 issue.tracker_id = 2
603 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
603 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
604 assert !issue.save, "Issue was saved"
604 assert !issue.save, "Issue was saved"
605 assert_equal ["Foo can't be blank", "Start date can't be blank"], issue.errors.full_messages.sort
605 assert_equal ["Foo can't be blank", "Start date can't be blank"], issue.errors.full_messages.sort
606
606
607 issue.start_date = Date.today
607 issue.start_date = Date.today
608 issue.custom_field_values = {cf.id.to_s => 'bar'}
608 issue.custom_field_values = {cf.id.to_s => 'bar'}
609 assert issue.save
609 assert issue.save
610 end
610 end
611
611
612 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
612 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
613 WorkflowPermission.delete_all
613 WorkflowPermission.delete_all
614 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
614 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
615 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'required')
615 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'required')
616 user = User.find(2)
616 user = User.find(2)
617 member = Member.find(1)
617 member = Member.find(1)
618 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
618 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
619
619
620 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
620 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
621
621
622 member.role_ids = [1, 2]
622 member.role_ids = [1, 2]
623 member.save!
623 member.save!
624 assert_equal [], issue.required_attribute_names(user.reload)
624 assert_equal [], issue.required_attribute_names(user.reload)
625
625
626 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'required')
626 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'required')
627 assert_equal %w(due_date), issue.required_attribute_names(user)
627 assert_equal %w(due_date), issue.required_attribute_names(user)
628
628
629 member.role_ids = [1, 2, 3]
629 member.role_ids = [1, 2, 3]
630 member.save!
630 member.save!
631 assert_equal [], issue.required_attribute_names(user.reload)
631 assert_equal [], issue.required_attribute_names(user.reload)
632
632
633 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
633 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
634 # required + readonly => required
634 # required + readonly => required
635 assert_equal %w(due_date), issue.required_attribute_names(user)
635 assert_equal %w(due_date), issue.required_attribute_names(user)
636 end
636 end
637
637
638 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
638 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
639 WorkflowPermission.delete_all
639 WorkflowPermission.delete_all
640 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
640 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
641 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
641 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
642 user = User.find(2)
642 user = User.find(2)
643 member = Member.find(1)
643 member = Member.find(1)
644 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
644 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
645
645
646 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
646 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
647
647
648 member.role_ids = [1, 2]
648 member.role_ids = [1, 2]
649 member.save!
649 member.save!
650 assert_equal [], issue.read_only_attribute_names(user.reload)
650 assert_equal [], issue.read_only_attribute_names(user.reload)
651
651
652 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
652 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
653 assert_equal %w(due_date), issue.read_only_attribute_names(user)
653 assert_equal %w(due_date), issue.read_only_attribute_names(user)
654 end
654 end
655
655
656 def test_copy
656 def test_copy
657 issue = Issue.new.copy_from(1)
657 issue = Issue.new.copy_from(1)
658 assert issue.copy?
658 assert issue.copy?
659 assert issue.save
659 assert issue.save
660 issue.reload
660 issue.reload
661 orig = Issue.find(1)
661 orig = Issue.find(1)
662 assert_equal orig.subject, issue.subject
662 assert_equal orig.subject, issue.subject
663 assert_equal orig.tracker, issue.tracker
663 assert_equal orig.tracker, issue.tracker
664 assert_equal "125", issue.custom_value_for(2).value
664 assert_equal "125", issue.custom_value_for(2).value
665 end
665 end
666
666
667 def test_copy_should_copy_status
667 def test_copy_should_copy_status
668 orig = Issue.find(8)
668 orig = Issue.find(8)
669 assert orig.status != IssueStatus.default
669 assert orig.status != IssueStatus.default
670
670
671 issue = Issue.new.copy_from(orig)
671 issue = Issue.new.copy_from(orig)
672 assert issue.save
672 assert issue.save
673 issue.reload
673 issue.reload
674 assert_equal orig.status, issue.status
674 assert_equal orig.status, issue.status
675 end
675 end
676
676
677 def test_copy_should_add_relation_with_copied_issue
677 def test_copy_should_add_relation_with_copied_issue
678 copied = Issue.find(1)
678 copied = Issue.find(1)
679 issue = Issue.new.copy_from(copied)
679 issue = Issue.new.copy_from(copied)
680 assert issue.save
680 assert issue.save
681 issue.reload
681 issue.reload
682
682
683 assert_equal 1, issue.relations.size
683 assert_equal 1, issue.relations.size
684 relation = issue.relations.first
684 relation = issue.relations.first
685 assert_equal 'copied_to', relation.relation_type
685 assert_equal 'copied_to', relation.relation_type
686 assert_equal copied, relation.issue_from
686 assert_equal copied, relation.issue_from
687 assert_equal issue, relation.issue_to
687 assert_equal issue, relation.issue_to
688 end
688 end
689
689
690 def test_copy_should_copy_subtasks
690 def test_copy_should_copy_subtasks
691 issue = Issue.generate_with_descendants!
691 issue = Issue.generate_with_descendants!
692
692
693 copy = issue.reload.copy
693 copy = issue.reload.copy
694 copy.author = User.find(7)
694 copy.author = User.find(7)
695 assert_difference 'Issue.count', 1+issue.descendants.count do
695 assert_difference 'Issue.count', 1+issue.descendants.count do
696 assert copy.save
696 assert copy.save
697 end
697 end
698 copy.reload
698 copy.reload
699 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
699 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
700 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
700 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
701 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
701 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
702 assert_equal copy.author, child_copy.author
702 assert_equal copy.author, child_copy.author
703 end
703 end
704
704
705 def test_copy_should_copy_subtasks_to_target_project
705 def test_copy_should_copy_subtasks_to_target_project
706 issue = Issue.generate_with_descendants!
706 issue = Issue.generate_with_descendants!
707
707
708 copy = issue.copy(:project_id => 3)
708 copy = issue.copy(:project_id => 3)
709 assert_difference 'Issue.count', 1+issue.descendants.count do
709 assert_difference 'Issue.count', 1+issue.descendants.count do
710 assert copy.save
710 assert copy.save
711 end
711 end
712 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
712 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
713 end
713 end
714
714
715 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
715 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
716 issue = Issue.generate_with_descendants!
716 issue = Issue.generate_with_descendants!
717
717
718 copy = issue.reload.copy
718 copy = issue.reload.copy
719 assert_difference 'Issue.count', 1+issue.descendants.count do
719 assert_difference 'Issue.count', 1+issue.descendants.count do
720 assert copy.save
720 assert copy.save
721 assert copy.save
721 assert copy.save
722 end
722 end
723 end
723 end
724
724
725 def test_should_not_call_after_project_change_on_creation
725 def test_should_not_call_after_project_change_on_creation
726 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Test', :author_id => 1)
726 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Test', :author_id => 1)
727 issue.expects(:after_project_change).never
727 issue.expects(:after_project_change).never
728 issue.save!
728 issue.save!
729 end
729 end
730
730
731 def test_should_not_call_after_project_change_on_update
731 def test_should_not_call_after_project_change_on_update
732 issue = Issue.find(1)
732 issue = Issue.find(1)
733 issue.project = Project.find(1)
733 issue.project = Project.find(1)
734 issue.subject = 'No project change'
734 issue.subject = 'No project change'
735 issue.expects(:after_project_change).never
735 issue.expects(:after_project_change).never
736 issue.save!
736 issue.save!
737 end
737 end
738
738
739 def test_should_call_after_project_change_on_project_change
739 def test_should_call_after_project_change_on_project_change
740 issue = Issue.find(1)
740 issue = Issue.find(1)
741 issue.project = Project.find(2)
741 issue.project = Project.find(2)
742 issue.expects(:after_project_change).once
742 issue.expects(:after_project_change).once
743 issue.save!
743 issue.save!
744 end
744 end
745
745
746 def test_adding_journal_should_update_timestamp
746 def test_adding_journal_should_update_timestamp
747 issue = Issue.find(1)
747 issue = Issue.find(1)
748 updated_on_was = issue.updated_on
748 updated_on_was = issue.updated_on
749
749
750 issue.init_journal(User.first, "Adding notes")
750 issue.init_journal(User.first, "Adding notes")
751 assert_difference 'Journal.count' do
751 assert_difference 'Journal.count' do
752 assert issue.save
752 assert issue.save
753 end
753 end
754 issue.reload
754 issue.reload
755
755
756 assert_not_equal updated_on_was, issue.updated_on
756 assert_not_equal updated_on_was, issue.updated_on
757 end
757 end
758
758
759 def test_should_close_duplicates
759 def test_should_close_duplicates
760 # Create 3 issues
760 # Create 3 issues
761 issue1 = Issue.generate!
761 issue1 = Issue.generate!
762 issue2 = Issue.generate!
762 issue2 = Issue.generate!
763 issue3 = Issue.generate!
763 issue3 = Issue.generate!
764
764
765 # 2 is a dupe of 1
765 # 2 is a dupe of 1
766 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
766 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
767 # And 3 is a dupe of 2
767 # And 3 is a dupe of 2
768 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
768 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
769 # And 3 is a dupe of 1 (circular duplicates)
769 # And 3 is a dupe of 1 (circular duplicates)
770 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
770 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
771
771
772 assert issue1.reload.duplicates.include?(issue2)
772 assert issue1.reload.duplicates.include?(issue2)
773
773
774 # Closing issue 1
774 # Closing issue 1
775 issue1.init_journal(User.find(:first), "Closing issue1")
775 issue1.init_journal(User.find(:first), "Closing issue1")
776 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
776 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
777 assert issue1.save
777 assert issue1.save
778 # 2 and 3 should be also closed
778 # 2 and 3 should be also closed
779 assert issue2.reload.closed?
779 assert issue2.reload.closed?
780 assert issue3.reload.closed?
780 assert issue3.reload.closed?
781 end
781 end
782
782
783 def test_should_not_close_duplicated_issue
783 def test_should_not_close_duplicated_issue
784 issue1 = Issue.generate!
784 issue1 = Issue.generate!
785 issue2 = Issue.generate!
785 issue2 = Issue.generate!
786
786
787 # 2 is a dupe of 1
787 # 2 is a dupe of 1
788 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
788 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
789 # 2 is a dup of 1 but 1 is not a duplicate of 2
789 # 2 is a dup of 1 but 1 is not a duplicate of 2
790 assert !issue2.reload.duplicates.include?(issue1)
790 assert !issue2.reload.duplicates.include?(issue1)
791
791
792 # Closing issue 2
792 # Closing issue 2
793 issue2.init_journal(User.find(:first), "Closing issue2")
793 issue2.init_journal(User.find(:first), "Closing issue2")
794 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
794 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
795 assert issue2.save
795 assert issue2.save
796 # 1 should not be also closed
796 # 1 should not be also closed
797 assert !issue1.reload.closed?
797 assert !issue1.reload.closed?
798 end
798 end
799
799
800 def test_assignable_versions
800 def test_assignable_versions
801 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
801 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
802 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
802 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
803 end
803 end
804
804
805 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
805 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
806 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
806 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
807 assert !issue.save
807 assert !issue.save
808 assert_not_nil issue.errors[:fixed_version_id]
808 assert_not_nil issue.errors[:fixed_version_id]
809 end
809 end
810
810
811 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
811 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
812 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
812 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
813 assert !issue.save
813 assert !issue.save
814 assert_not_nil issue.errors[:fixed_version_id]
814 assert_not_nil issue.errors[:fixed_version_id]
815 end
815 end
816
816
817 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
817 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
818 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
818 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
819 assert issue.save
819 assert issue.save
820 end
820 end
821
821
822 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
822 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
823 issue = Issue.find(11)
823 issue = Issue.find(11)
824 assert_equal 'closed', issue.fixed_version.status
824 assert_equal 'closed', issue.fixed_version.status
825 issue.subject = 'Subject changed'
825 issue.subject = 'Subject changed'
826 assert issue.save
826 assert issue.save
827 end
827 end
828
828
829 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
829 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
830 issue = Issue.find(11)
830 issue = Issue.find(11)
831 issue.status_id = 1
831 issue.status_id = 1
832 assert !issue.save
832 assert !issue.save
833 assert_not_nil issue.errors[:base]
833 assert_not_nil issue.errors[:base]
834 end
834 end
835
835
836 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
836 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
837 issue = Issue.find(11)
837 issue = Issue.find(11)
838 issue.status_id = 1
838 issue.status_id = 1
839 issue.fixed_version_id = 3
839 issue.fixed_version_id = 3
840 assert issue.save
840 assert issue.save
841 end
841 end
842
842
843 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
843 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
844 issue = Issue.find(12)
844 issue = Issue.find(12)
845 assert_equal 'locked', issue.fixed_version.status
845 assert_equal 'locked', issue.fixed_version.status
846 issue.status_id = 1
846 issue.status_id = 1
847 assert issue.save
847 assert issue.save
848 end
848 end
849
849
850 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
850 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
851 issue = Issue.find(2)
851 issue = Issue.find(2)
852 assert_equal 2, issue.fixed_version_id
852 assert_equal 2, issue.fixed_version_id
853 issue.project_id = 3
853 issue.project_id = 3
854 assert_nil issue.fixed_version_id
854 assert_nil issue.fixed_version_id
855 issue.fixed_version_id = 2
855 issue.fixed_version_id = 2
856 assert !issue.save
856 assert !issue.save
857 assert_include 'Target version is not included in the list', issue.errors.full_messages
857 assert_include 'Target version is not included in the list', issue.errors.full_messages
858 end
858 end
859
859
860 def test_should_keep_shared_version_when_changing_project
860 def test_should_keep_shared_version_when_changing_project
861 Version.find(2).update_attribute :sharing, 'tree'
861 Version.find(2).update_attribute :sharing, 'tree'
862
862
863 issue = Issue.find(2)
863 issue = Issue.find(2)
864 assert_equal 2, issue.fixed_version_id
864 assert_equal 2, issue.fixed_version_id
865 issue.project_id = 3
865 issue.project_id = 3
866 assert_equal 2, issue.fixed_version_id
866 assert_equal 2, issue.fixed_version_id
867 assert issue.save
867 assert issue.save
868 end
868 end
869
869
870 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
870 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
871 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
871 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
872 end
872 end
873
873
874 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
874 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
875 Project.find(2).disable_module! :issue_tracking
875 Project.find(2).disable_module! :issue_tracking
876 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
876 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
877 end
877 end
878
878
879 def test_move_to_another_project_with_same_category
879 def test_move_to_another_project_with_same_category
880 issue = Issue.find(1)
880 issue = Issue.find(1)
881 issue.project = Project.find(2)
881 issue.project = Project.find(2)
882 assert issue.save
882 assert issue.save
883 issue.reload
883 issue.reload
884 assert_equal 2, issue.project_id
884 assert_equal 2, issue.project_id
885 # Category changes
885 # Category changes
886 assert_equal 4, issue.category_id
886 assert_equal 4, issue.category_id
887 # Make sure time entries were move to the target project
887 # Make sure time entries were move to the target project
888 assert_equal 2, issue.time_entries.first.project_id
888 assert_equal 2, issue.time_entries.first.project_id
889 end
889 end
890
890
891 def test_move_to_another_project_without_same_category
891 def test_move_to_another_project_without_same_category
892 issue = Issue.find(2)
892 issue = Issue.find(2)
893 issue.project = Project.find(2)
893 issue.project = Project.find(2)
894 assert issue.save
894 assert issue.save
895 issue.reload
895 issue.reload
896 assert_equal 2, issue.project_id
896 assert_equal 2, issue.project_id
897 # Category cleared
897 # Category cleared
898 assert_nil issue.category_id
898 assert_nil issue.category_id
899 end
899 end
900
900
901 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
901 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
902 issue = Issue.find(1)
902 issue = Issue.find(1)
903 issue.update_attribute(:fixed_version_id, 1)
903 issue.update_attribute(:fixed_version_id, 1)
904 issue.project = Project.find(2)
904 issue.project = Project.find(2)
905 assert issue.save
905 assert issue.save
906 issue.reload
906 issue.reload
907 assert_equal 2, issue.project_id
907 assert_equal 2, issue.project_id
908 # Cleared fixed_version
908 # Cleared fixed_version
909 assert_equal nil, issue.fixed_version
909 assert_equal nil, issue.fixed_version
910 end
910 end
911
911
912 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
912 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
913 issue = Issue.find(1)
913 issue = Issue.find(1)
914 issue.update_attribute(:fixed_version_id, 4)
914 issue.update_attribute(:fixed_version_id, 4)
915 issue.project = Project.find(5)
915 issue.project = Project.find(5)
916 assert issue.save
916 assert issue.save
917 issue.reload
917 issue.reload
918 assert_equal 5, issue.project_id
918 assert_equal 5, issue.project_id
919 # Keep fixed_version
919 # Keep fixed_version
920 assert_equal 4, issue.fixed_version_id
920 assert_equal 4, issue.fixed_version_id
921 end
921 end
922
922
923 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
923 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
924 issue = Issue.find(1)
924 issue = Issue.find(1)
925 issue.update_attribute(:fixed_version_id, 1)
925 issue.update_attribute(:fixed_version_id, 1)
926 issue.project = Project.find(5)
926 issue.project = Project.find(5)
927 assert issue.save
927 assert issue.save
928 issue.reload
928 issue.reload
929 assert_equal 5, issue.project_id
929 assert_equal 5, issue.project_id
930 # Cleared fixed_version
930 # Cleared fixed_version
931 assert_equal nil, issue.fixed_version
931 assert_equal nil, issue.fixed_version
932 end
932 end
933
933
934 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
934 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
935 issue = Issue.find(1)
935 issue = Issue.find(1)
936 issue.update_attribute(:fixed_version_id, 7)
936 issue.update_attribute(:fixed_version_id, 7)
937 issue.project = Project.find(2)
937 issue.project = Project.find(2)
938 assert issue.save
938 assert issue.save
939 issue.reload
939 issue.reload
940 assert_equal 2, issue.project_id
940 assert_equal 2, issue.project_id
941 # Keep fixed_version
941 # Keep fixed_version
942 assert_equal 7, issue.fixed_version_id
942 assert_equal 7, issue.fixed_version_id
943 end
943 end
944
944
945 def test_move_to_another_project_should_keep_parent_if_valid
945 def test_move_to_another_project_should_keep_parent_if_valid
946 issue = Issue.find(1)
946 issue = Issue.find(1)
947 issue.update_attribute(:parent_issue_id, 2)
947 issue.update_attribute(:parent_issue_id, 2)
948 issue.project = Project.find(3)
948 issue.project = Project.find(3)
949 assert issue.save
949 assert issue.save
950 issue.reload
950 issue.reload
951 assert_equal 2, issue.parent_id
951 assert_equal 2, issue.parent_id
952 end
952 end
953
953
954 def test_move_to_another_project_should_clear_parent_if_not_valid
954 def test_move_to_another_project_should_clear_parent_if_not_valid
955 issue = Issue.find(1)
955 issue = Issue.find(1)
956 issue.update_attribute(:parent_issue_id, 2)
956 issue.update_attribute(:parent_issue_id, 2)
957 issue.project = Project.find(2)
957 issue.project = Project.find(2)
958 assert issue.save
958 assert issue.save
959 issue.reload
959 issue.reload
960 assert_nil issue.parent_id
960 assert_nil issue.parent_id
961 end
961 end
962
962
963 def test_move_to_another_project_with_disabled_tracker
963 def test_move_to_another_project_with_disabled_tracker
964 issue = Issue.find(1)
964 issue = Issue.find(1)
965 target = Project.find(2)
965 target = Project.find(2)
966 target.tracker_ids = [3]
966 target.tracker_ids = [3]
967 target.save
967 target.save
968 issue.project = target
968 issue.project = target
969 assert issue.save
969 assert issue.save
970 issue.reload
970 issue.reload
971 assert_equal 2, issue.project_id
971 assert_equal 2, issue.project_id
972 assert_equal 3, issue.tracker_id
972 assert_equal 3, issue.tracker_id
973 end
973 end
974
974
975 def test_copy_to_the_same_project
975 def test_copy_to_the_same_project
976 issue = Issue.find(1)
976 issue = Issue.find(1)
977 copy = issue.copy
977 copy = issue.copy
978 assert_difference 'Issue.count' do
978 assert_difference 'Issue.count' do
979 copy.save!
979 copy.save!
980 end
980 end
981 assert_kind_of Issue, copy
981 assert_kind_of Issue, copy
982 assert_equal issue.project, copy.project
982 assert_equal issue.project, copy.project
983 assert_equal "125", copy.custom_value_for(2).value
983 assert_equal "125", copy.custom_value_for(2).value
984 end
984 end
985
985
986 def test_copy_to_another_project_and_tracker
986 def test_copy_to_another_project_and_tracker
987 issue = Issue.find(1)
987 issue = Issue.find(1)
988 copy = issue.copy(:project_id => 3, :tracker_id => 2)
988 copy = issue.copy(:project_id => 3, :tracker_id => 2)
989 assert_difference 'Issue.count' do
989 assert_difference 'Issue.count' do
990 copy.save!
990 copy.save!
991 end
991 end
992 copy.reload
992 copy.reload
993 assert_kind_of Issue, copy
993 assert_kind_of Issue, copy
994 assert_equal Project.find(3), copy.project
994 assert_equal Project.find(3), copy.project
995 assert_equal Tracker.find(2), copy.tracker
995 assert_equal Tracker.find(2), copy.tracker
996 # Custom field #2 is not associated with target tracker
996 # Custom field #2 is not associated with target tracker
997 assert_nil copy.custom_value_for(2)
997 assert_nil copy.custom_value_for(2)
998 end
998 end
999
999
1000 context "#copy" do
1000 context "#copy" do
1001 setup do
1001 setup do
1002 @issue = Issue.find(1)
1002 @issue = Issue.find(1)
1003 end
1003 end
1004
1004
1005 should "not create a journal" do
1005 should "not create a journal" do
1006 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1006 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1007 copy.save!
1007 copy.save!
1008 assert_equal 0, copy.reload.journals.size
1008 assert_equal 0, copy.reload.journals.size
1009 end
1009 end
1010
1010
1011 should "allow assigned_to changes" do
1011 should "allow assigned_to changes" do
1012 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1012 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1013 assert_equal 3, copy.assigned_to_id
1013 assert_equal 3, copy.assigned_to_id
1014 end
1014 end
1015
1015
1016 should "allow status changes" do
1016 should "allow status changes" do
1017 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1017 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1018 assert_equal 2, copy.status_id
1018 assert_equal 2, copy.status_id
1019 end
1019 end
1020
1020
1021 should "allow start date changes" do
1021 should "allow start date changes" do
1022 date = Date.today
1022 date = Date.today
1023 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1023 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1024 assert_equal date, copy.start_date
1024 assert_equal date, copy.start_date
1025 end
1025 end
1026
1026
1027 should "allow due date changes" do
1027 should "allow due date changes" do
1028 date = Date.today
1028 date = Date.today
1029 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1029 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1030 assert_equal date, copy.due_date
1030 assert_equal date, copy.due_date
1031 end
1031 end
1032
1032
1033 should "set current user as author" do
1033 should "set current user as author" do
1034 User.current = User.find(9)
1034 User.current = User.find(9)
1035 copy = @issue.copy(:project_id => 3, :tracker_id => 2)
1035 copy = @issue.copy(:project_id => 3, :tracker_id => 2)
1036 assert_equal User.current, copy.author
1036 assert_equal User.current, copy.author
1037 end
1037 end
1038
1038
1039 should "create a journal with notes" do
1039 should "create a journal with notes" do
1040 date = Date.today
1040 date = Date.today
1041 notes = "Notes added when copying"
1041 notes = "Notes added when copying"
1042 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1042 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1043 copy.init_journal(User.current, notes)
1043 copy.init_journal(User.current, notes)
1044 copy.save!
1044 copy.save!
1045
1045
1046 assert_equal 1, copy.journals.size
1046 assert_equal 1, copy.journals.size
1047 journal = copy.journals.first
1047 journal = copy.journals.first
1048 assert_equal 0, journal.details.size
1048 assert_equal 0, journal.details.size
1049 assert_equal notes, journal.notes
1049 assert_equal notes, journal.notes
1050 end
1050 end
1051 end
1051 end
1052
1052
1053 def test_valid_parent_project
1053 def test_valid_parent_project
1054 issue = Issue.find(1)
1054 issue = Issue.find(1)
1055 issue_in_same_project = Issue.find(2)
1055 issue_in_same_project = Issue.find(2)
1056 issue_in_child_project = Issue.find(5)
1056 issue_in_child_project = Issue.find(5)
1057 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1057 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1058 issue_in_other_child_project = Issue.find(6)
1058 issue_in_other_child_project = Issue.find(6)
1059 issue_in_different_tree = Issue.find(4)
1059 issue_in_different_tree = Issue.find(4)
1060
1060
1061 with_settings :cross_project_subtasks => '' do
1061 with_settings :cross_project_subtasks => '' do
1062 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1062 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1063 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1063 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1064 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1064 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1065 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1065 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1066 end
1066 end
1067
1067
1068 with_settings :cross_project_subtasks => 'system' do
1068 with_settings :cross_project_subtasks => 'system' do
1069 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1069 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1070 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1070 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1071 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1071 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1072 end
1072 end
1073
1073
1074 with_settings :cross_project_subtasks => 'tree' do
1074 with_settings :cross_project_subtasks => 'tree' do
1075 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1075 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1076 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1076 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1077 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1077 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1078 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1078 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1079
1079
1080 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1080 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1081 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1081 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1082 end
1082 end
1083
1083
1084 with_settings :cross_project_subtasks => 'descendants' do
1084 with_settings :cross_project_subtasks => 'descendants' do
1085 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1085 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1086 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1086 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1087 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1087 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1088 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1088 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1089
1089
1090 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1090 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1091 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1091 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1092 end
1092 end
1093 end
1093 end
1094
1094
1095 def test_recipients_should_include_previous_assignee
1095 def test_recipients_should_include_previous_assignee
1096 user = User.find(3)
1096 user = User.find(3)
1097 user.members.update_all ["mail_notification = ?", false]
1097 user.members.update_all ["mail_notification = ?", false]
1098 user.update_attribute :mail_notification, 'only_assigned'
1098 user.update_attribute :mail_notification, 'only_assigned'
1099
1099
1100 issue = Issue.find(2)
1100 issue = Issue.find(2)
1101 issue.assigned_to = nil
1101 issue.assigned_to = nil
1102 assert_include user.mail, issue.recipients
1102 assert_include user.mail, issue.recipients
1103 issue.save!
1103 issue.save!
1104 assert !issue.recipients.include?(user.mail)
1104 assert !issue.recipients.include?(user.mail)
1105 end
1105 end
1106
1106
1107 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1107 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1108 issue = Issue.find(12)
1108 issue = Issue.find(12)
1109 assert issue.recipients.include?(issue.author.mail)
1109 assert issue.recipients.include?(issue.author.mail)
1110 # copy the issue to a private project
1110 # copy the issue to a private project
1111 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1111 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1112 # author is not a member of project anymore
1112 # author is not a member of project anymore
1113 assert !copy.recipients.include?(copy.author.mail)
1113 assert !copy.recipients.include?(copy.author.mail)
1114 end
1114 end
1115
1115
1116 def test_recipients_should_include_the_assigned_group_members
1116 def test_recipients_should_include_the_assigned_group_members
1117 group_member = User.generate!
1117 group_member = User.generate!
1118 group = Group.generate!
1118 group = Group.generate!
1119 group.users << group_member
1119 group.users << group_member
1120
1120
1121 issue = Issue.find(12)
1121 issue = Issue.find(12)
1122 issue.assigned_to = group
1122 issue.assigned_to = group
1123 assert issue.recipients.include?(group_member.mail)
1123 assert issue.recipients.include?(group_member.mail)
1124 end
1124 end
1125
1125
1126 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1126 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1127 user = User.find(3)
1127 user = User.find(3)
1128 issue = Issue.find(9)
1128 issue = Issue.find(9)
1129 Watcher.create!(:user => user, :watchable => issue)
1129 Watcher.create!(:user => user, :watchable => issue)
1130 assert issue.watched_by?(user)
1130 assert issue.watched_by?(user)
1131 assert !issue.watcher_recipients.include?(user.mail)
1131 assert !issue.watcher_recipients.include?(user.mail)
1132 end
1132 end
1133
1133
1134 def test_issue_destroy
1134 def test_issue_destroy
1135 Issue.find(1).destroy
1135 Issue.find(1).destroy
1136 assert_nil Issue.find_by_id(1)
1136 assert_nil Issue.find_by_id(1)
1137 assert_nil TimeEntry.find_by_issue_id(1)
1137 assert_nil TimeEntry.find_by_issue_id(1)
1138 end
1138 end
1139
1139
1140 def test_destroying_a_deleted_issue_should_not_raise_an_error
1140 def test_destroying_a_deleted_issue_should_not_raise_an_error
1141 issue = Issue.find(1)
1141 issue = Issue.find(1)
1142 Issue.find(1).destroy
1142 Issue.find(1).destroy
1143
1143
1144 assert_nothing_raised do
1144 assert_nothing_raised do
1145 assert_no_difference 'Issue.count' do
1145 assert_no_difference 'Issue.count' do
1146 issue.destroy
1146 issue.destroy
1147 end
1147 end
1148 assert issue.destroyed?
1148 assert issue.destroyed?
1149 end
1149 end
1150 end
1150 end
1151
1151
1152 def test_destroying_a_stale_issue_should_not_raise_an_error
1152 def test_destroying_a_stale_issue_should_not_raise_an_error
1153 issue = Issue.find(1)
1153 issue = Issue.find(1)
1154 Issue.find(1).update_attribute :subject, "Updated"
1154 Issue.find(1).update_attribute :subject, "Updated"
1155
1155
1156 assert_nothing_raised do
1156 assert_nothing_raised do
1157 assert_difference 'Issue.count', -1 do
1157 assert_difference 'Issue.count', -1 do
1158 issue.destroy
1158 issue.destroy
1159 end
1159 end
1160 assert issue.destroyed?
1160 assert issue.destroyed?
1161 end
1161 end
1162 end
1162 end
1163
1163
1164 def test_blocked
1164 def test_blocked
1165 blocked_issue = Issue.find(9)
1165 blocked_issue = Issue.find(9)
1166 blocking_issue = Issue.find(10)
1166 blocking_issue = Issue.find(10)
1167
1167
1168 assert blocked_issue.blocked?
1168 assert blocked_issue.blocked?
1169 assert !blocking_issue.blocked?
1169 assert !blocking_issue.blocked?
1170 end
1170 end
1171
1171
1172 def test_blocked_issues_dont_allow_closed_statuses
1172 def test_blocked_issues_dont_allow_closed_statuses
1173 blocked_issue = Issue.find(9)
1173 blocked_issue = Issue.find(9)
1174
1174
1175 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1175 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1176 assert !allowed_statuses.empty?
1176 assert !allowed_statuses.empty?
1177 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1177 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1178 assert closed_statuses.empty?
1178 assert closed_statuses.empty?
1179 end
1179 end
1180
1180
1181 def test_unblocked_issues_allow_closed_statuses
1181 def test_unblocked_issues_allow_closed_statuses
1182 blocking_issue = Issue.find(10)
1182 blocking_issue = Issue.find(10)
1183
1183
1184 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1184 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1185 assert !allowed_statuses.empty?
1185 assert !allowed_statuses.empty?
1186 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1186 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1187 assert !closed_statuses.empty?
1187 assert !closed_statuses.empty?
1188 end
1188 end
1189
1189
1190 def test_rescheduling_an_issue_should_reschedule_following_issue
1190 def test_rescheduling_an_issue_should_reschedule_following_issue
1191 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
1191 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1,
1192 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
1192 :author_id => 1, :status_id => 1,
1193 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1193 :subject => '-',
1194 :start_date => Date.today, :due_date => Date.today + 2)
1195 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1,
1196 :author_id => 1, :status_id => 1,
1197 :subject => '-',
1198 :start_date => Date.today, :due_date => Date.today + 2)
1199 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1200 :relation_type => IssueRelation::TYPE_PRECEDES)
1194 assert_equal issue1.due_date + 1, issue2.reload.start_date
1201 assert_equal issue1.due_date + 1, issue2.reload.start_date
1195
1202
1196 issue1.due_date = Date.today + 5
1203 issue1.due_date = Date.today + 5
1197 issue1.save!
1204 issue1.save!
1198 assert_equal issue1.due_date + 1, issue2.reload.start_date
1205 assert_equal issue1.due_date + 1, issue2.reload.start_date
1199 end
1206 end
1200
1207
1201 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1208 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1202 stale = Issue.find(1)
1209 stale = Issue.find(1)
1203 issue = Issue.find(1)
1210 issue = Issue.find(1)
1204 issue.subject = "Updated"
1211 issue.subject = "Updated"
1205 issue.save!
1212 issue.save!
1206
1213
1207 date = 10.days.from_now.to_date
1214 date = 10.days.from_now.to_date
1208 assert_nothing_raised do
1215 assert_nothing_raised do
1209 stale.reschedule_after(date)
1216 stale.reschedule_after(date)
1210 end
1217 end
1211 assert_equal date, stale.reload.start_date
1218 assert_equal date, stale.reload.start_date
1212 end
1219 end
1213
1220
1214 def test_overdue
1221 def test_overdue
1215 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1222 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1216 assert !Issue.new(:due_date => Date.today).overdue?
1223 assert !Issue.new(:due_date => Date.today).overdue?
1217 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1224 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1218 assert !Issue.new(:due_date => nil).overdue?
1225 assert !Issue.new(:due_date => nil).overdue?
1219 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
1226 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
1220 end
1227 end
1221
1228
1222 context "#behind_schedule?" do
1229 context "#behind_schedule?" do
1223 should "be false if the issue has no start_date" do
1230 should "be false if the issue has no start_date" do
1224 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
1231 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
1225 end
1232 end
1226
1233
1227 should "be false if the issue has no end_date" do
1234 should "be false if the issue has no end_date" do
1228 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
1235 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
1229 end
1236 end
1230
1237
1231 should "be false if the issue has more done than it's calendar time" do
1238 should "be false if the issue has more done than it's calendar time" do
1232 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
1239 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
1233 end
1240 end
1234
1241
1235 should "be true if the issue hasn't been started at all" do
1242 should "be true if the issue hasn't been started at all" do
1236 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
1243 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
1237 end
1244 end
1238
1245
1239 should "be true if the issue has used more calendar time than it's done ratio" do
1246 should "be true if the issue has used more calendar time than it's done ratio" do
1240 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
1247 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
1241 end
1248 end
1242 end
1249 end
1243
1250
1244 context "#assignable_users" do
1251 context "#assignable_users" do
1245 should "be Users" do
1252 should "be Users" do
1246 assert_kind_of User, Issue.find(1).assignable_users.first
1253 assert_kind_of User, Issue.find(1).assignable_users.first
1247 end
1254 end
1248
1255
1249 should "include the issue author" do
1256 should "include the issue author" do
1250 non_project_member = User.generate!
1257 non_project_member = User.generate!
1251 issue = Issue.generate!(:author => non_project_member)
1258 issue = Issue.generate!(:author => non_project_member)
1252
1259
1253 assert issue.assignable_users.include?(non_project_member)
1260 assert issue.assignable_users.include?(non_project_member)
1254 end
1261 end
1255
1262
1256 should "include the current assignee" do
1263 should "include the current assignee" do
1257 user = User.generate!
1264 user = User.generate!
1258 issue = Issue.generate!(:assigned_to => user)
1265 issue = Issue.generate!(:assigned_to => user)
1259 user.lock!
1266 user.lock!
1260
1267
1261 assert Issue.find(issue.id).assignable_users.include?(user)
1268 assert Issue.find(issue.id).assignable_users.include?(user)
1262 end
1269 end
1263
1270
1264 should "not show the issue author twice" do
1271 should "not show the issue author twice" do
1265 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1272 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1266 assert_equal 2, assignable_user_ids.length
1273 assert_equal 2, assignable_user_ids.length
1267
1274
1268 assignable_user_ids.each do |user_id|
1275 assignable_user_ids.each do |user_id|
1269 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
1276 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
1270 end
1277 end
1271 end
1278 end
1272
1279
1273 context "with issue_group_assignment" do
1280 context "with issue_group_assignment" do
1274 should "include groups" do
1281 should "include groups" do
1275 issue = Issue.new(:project => Project.find(2))
1282 issue = Issue.new(:project => Project.find(2))
1276
1283
1277 with_settings :issue_group_assignment => '1' do
1284 with_settings :issue_group_assignment => '1' do
1278 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1285 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1279 assert issue.assignable_users.include?(Group.find(11))
1286 assert issue.assignable_users.include?(Group.find(11))
1280 end
1287 end
1281 end
1288 end
1282 end
1289 end
1283
1290
1284 context "without issue_group_assignment" do
1291 context "without issue_group_assignment" do
1285 should "not include groups" do
1292 should "not include groups" do
1286 issue = Issue.new(:project => Project.find(2))
1293 issue = Issue.new(:project => Project.find(2))
1287
1294
1288 with_settings :issue_group_assignment => '0' do
1295 with_settings :issue_group_assignment => '0' do
1289 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1296 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1290 assert !issue.assignable_users.include?(Group.find(11))
1297 assert !issue.assignable_users.include?(Group.find(11))
1291 end
1298 end
1292 end
1299 end
1293 end
1300 end
1294 end
1301 end
1295
1302
1296 def test_create_should_send_email_notification
1303 def test_create_should_send_email_notification
1297 ActionMailer::Base.deliveries.clear
1304 ActionMailer::Base.deliveries.clear
1298 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1305 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1299 :author_id => 3, :status_id => 1,
1306 :author_id => 3, :status_id => 1,
1300 :priority => IssuePriority.all.first,
1307 :priority => IssuePriority.all.first,
1301 :subject => 'test_create', :estimated_hours => '1:30')
1308 :subject => 'test_create', :estimated_hours => '1:30')
1302
1309
1303 assert issue.save
1310 assert issue.save
1304 assert_equal 1, ActionMailer::Base.deliveries.size
1311 assert_equal 1, ActionMailer::Base.deliveries.size
1305 end
1312 end
1306
1313
1307 def test_stale_issue_should_not_send_email_notification
1314 def test_stale_issue_should_not_send_email_notification
1308 ActionMailer::Base.deliveries.clear
1315 ActionMailer::Base.deliveries.clear
1309 issue = Issue.find(1)
1316 issue = Issue.find(1)
1310 stale = Issue.find(1)
1317 stale = Issue.find(1)
1311
1318
1312 issue.init_journal(User.find(1))
1319 issue.init_journal(User.find(1))
1313 issue.subject = 'Subjet update'
1320 issue.subject = 'Subjet update'
1314 assert issue.save
1321 assert issue.save
1315 assert_equal 1, ActionMailer::Base.deliveries.size
1322 assert_equal 1, ActionMailer::Base.deliveries.size
1316 ActionMailer::Base.deliveries.clear
1323 ActionMailer::Base.deliveries.clear
1317
1324
1318 stale.init_journal(User.find(1))
1325 stale.init_journal(User.find(1))
1319 stale.subject = 'Another subjet update'
1326 stale.subject = 'Another subjet update'
1320 assert_raise ActiveRecord::StaleObjectError do
1327 assert_raise ActiveRecord::StaleObjectError do
1321 stale.save
1328 stale.save
1322 end
1329 end
1323 assert ActionMailer::Base.deliveries.empty?
1330 assert ActionMailer::Base.deliveries.empty?
1324 end
1331 end
1325
1332
1326 def test_journalized_description
1333 def test_journalized_description
1327 IssueCustomField.delete_all
1334 IssueCustomField.delete_all
1328
1335
1329 i = Issue.first
1336 i = Issue.first
1330 old_description = i.description
1337 old_description = i.description
1331 new_description = "This is the new description"
1338 new_description = "This is the new description"
1332
1339
1333 i.init_journal(User.find(2))
1340 i.init_journal(User.find(2))
1334 i.description = new_description
1341 i.description = new_description
1335 assert_difference 'Journal.count', 1 do
1342 assert_difference 'Journal.count', 1 do
1336 assert_difference 'JournalDetail.count', 1 do
1343 assert_difference 'JournalDetail.count', 1 do
1337 i.save!
1344 i.save!
1338 end
1345 end
1339 end
1346 end
1340
1347
1341 detail = JournalDetail.first(:order => 'id DESC')
1348 detail = JournalDetail.first(:order => 'id DESC')
1342 assert_equal i, detail.journal.journalized
1349 assert_equal i, detail.journal.journalized
1343 assert_equal 'attr', detail.property
1350 assert_equal 'attr', detail.property
1344 assert_equal 'description', detail.prop_key
1351 assert_equal 'description', detail.prop_key
1345 assert_equal old_description, detail.old_value
1352 assert_equal old_description, detail.old_value
1346 assert_equal new_description, detail.value
1353 assert_equal new_description, detail.value
1347 end
1354 end
1348
1355
1349 def test_blank_descriptions_should_not_be_journalized
1356 def test_blank_descriptions_should_not_be_journalized
1350 IssueCustomField.delete_all
1357 IssueCustomField.delete_all
1351 Issue.update_all("description = NULL", "id=1")
1358 Issue.update_all("description = NULL", "id=1")
1352
1359
1353 i = Issue.find(1)
1360 i = Issue.find(1)
1354 i.init_journal(User.find(2))
1361 i.init_journal(User.find(2))
1355 i.subject = "blank description"
1362 i.subject = "blank description"
1356 i.description = "\r\n"
1363 i.description = "\r\n"
1357
1364
1358 assert_difference 'Journal.count', 1 do
1365 assert_difference 'Journal.count', 1 do
1359 assert_difference 'JournalDetail.count', 1 do
1366 assert_difference 'JournalDetail.count', 1 do
1360 i.save!
1367 i.save!
1361 end
1368 end
1362 end
1369 end
1363 end
1370 end
1364
1371
1365 def test_journalized_multi_custom_field
1372 def test_journalized_multi_custom_field
1366 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
1373 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list', :is_filter => true, :is_for_all => true,
1367 :tracker_ids => [1], :possible_values => ['value1', 'value2', 'value3'], :multiple => true)
1374 :tracker_ids => [1], :possible_values => ['value1', 'value2', 'value3'], :multiple => true)
1368
1375
1369 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'Test', :author_id => 1)
1376 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'Test', :author_id => 1)
1370
1377
1371 assert_difference 'Journal.count' do
1378 assert_difference 'Journal.count' do
1372 assert_difference 'JournalDetail.count' do
1379 assert_difference 'JournalDetail.count' do
1373 issue.init_journal(User.first)
1380 issue.init_journal(User.first)
1374 issue.custom_field_values = {field.id => ['value1']}
1381 issue.custom_field_values = {field.id => ['value1']}
1375 issue.save!
1382 issue.save!
1376 end
1383 end
1377 assert_difference 'JournalDetail.count' do
1384 assert_difference 'JournalDetail.count' do
1378 issue.init_journal(User.first)
1385 issue.init_journal(User.first)
1379 issue.custom_field_values = {field.id => ['value1', 'value2']}
1386 issue.custom_field_values = {field.id => ['value1', 'value2']}
1380 issue.save!
1387 issue.save!
1381 end
1388 end
1382 assert_difference 'JournalDetail.count', 2 do
1389 assert_difference 'JournalDetail.count', 2 do
1383 issue.init_journal(User.first)
1390 issue.init_journal(User.first)
1384 issue.custom_field_values = {field.id => ['value3', 'value2']}
1391 issue.custom_field_values = {field.id => ['value3', 'value2']}
1385 issue.save!
1392 issue.save!
1386 end
1393 end
1387 assert_difference 'JournalDetail.count', 2 do
1394 assert_difference 'JournalDetail.count', 2 do
1388 issue.init_journal(User.first)
1395 issue.init_journal(User.first)
1389 issue.custom_field_values = {field.id => nil}
1396 issue.custom_field_values = {field.id => nil}
1390 issue.save!
1397 issue.save!
1391 end
1398 end
1392 end
1399 end
1393 end
1400 end
1394
1401
1395 def test_description_eol_should_be_normalized
1402 def test_description_eol_should_be_normalized
1396 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1403 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1397 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1404 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1398 end
1405 end
1399
1406
1400 def test_saving_twice_should_not_duplicate_journal_details
1407 def test_saving_twice_should_not_duplicate_journal_details
1401 i = Issue.find(:first)
1408 i = Issue.find(:first)
1402 i.init_journal(User.find(2), 'Some notes')
1409 i.init_journal(User.find(2), 'Some notes')
1403 # initial changes
1410 # initial changes
1404 i.subject = 'New subject'
1411 i.subject = 'New subject'
1405 i.done_ratio = i.done_ratio + 10
1412 i.done_ratio = i.done_ratio + 10
1406 assert_difference 'Journal.count' do
1413 assert_difference 'Journal.count' do
1407 assert i.save
1414 assert i.save
1408 end
1415 end
1409 # 1 more change
1416 # 1 more change
1410 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
1417 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
1411 assert_no_difference 'Journal.count' do
1418 assert_no_difference 'Journal.count' do
1412 assert_difference 'JournalDetail.count', 1 do
1419 assert_difference 'JournalDetail.count', 1 do
1413 i.save
1420 i.save
1414 end
1421 end
1415 end
1422 end
1416 # no more change
1423 # no more change
1417 assert_no_difference 'Journal.count' do
1424 assert_no_difference 'Journal.count' do
1418 assert_no_difference 'JournalDetail.count' do
1425 assert_no_difference 'JournalDetail.count' do
1419 i.save
1426 i.save
1420 end
1427 end
1421 end
1428 end
1422 end
1429 end
1423
1430
1424 def test_all_dependent_issues
1431 def test_all_dependent_issues
1425 IssueRelation.delete_all
1432 IssueRelation.delete_all
1426 assert IssueRelation.create!(:issue_from => Issue.find(1),
1433 assert IssueRelation.create!(:issue_from => Issue.find(1),
1427 :issue_to => Issue.find(2),
1434 :issue_to => Issue.find(2),
1428 :relation_type => IssueRelation::TYPE_PRECEDES)
1435 :relation_type => IssueRelation::TYPE_PRECEDES)
1429 assert IssueRelation.create!(:issue_from => Issue.find(2),
1436 assert IssueRelation.create!(:issue_from => Issue.find(2),
1430 :issue_to => Issue.find(3),
1437 :issue_to => Issue.find(3),
1431 :relation_type => IssueRelation::TYPE_PRECEDES)
1438 :relation_type => IssueRelation::TYPE_PRECEDES)
1432 assert IssueRelation.create!(:issue_from => Issue.find(3),
1439 assert IssueRelation.create!(:issue_from => Issue.find(3),
1433 :issue_to => Issue.find(8),
1440 :issue_to => Issue.find(8),
1434 :relation_type => IssueRelation::TYPE_PRECEDES)
1441 :relation_type => IssueRelation::TYPE_PRECEDES)
1435
1442
1436 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1443 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1437 end
1444 end
1438
1445
1439 def test_all_dependent_issues_with_persistent_circular_dependency
1446 def test_all_dependent_issues_with_persistent_circular_dependency
1440 IssueRelation.delete_all
1447 IssueRelation.delete_all
1441 assert IssueRelation.create!(:issue_from => Issue.find(1),
1448 assert IssueRelation.create!(:issue_from => Issue.find(1),
1442 :issue_to => Issue.find(2),
1449 :issue_to => Issue.find(2),
1443 :relation_type => IssueRelation::TYPE_PRECEDES)
1450 :relation_type => IssueRelation::TYPE_PRECEDES)
1444 assert IssueRelation.create!(:issue_from => Issue.find(2),
1451 assert IssueRelation.create!(:issue_from => Issue.find(2),
1445 :issue_to => Issue.find(3),
1452 :issue_to => Issue.find(3),
1446 :relation_type => IssueRelation::TYPE_PRECEDES)
1453 :relation_type => IssueRelation::TYPE_PRECEDES)
1447
1454
1448 r = IssueRelation.create!(:issue_from => Issue.find(3),
1455 r = IssueRelation.create!(:issue_from => Issue.find(3),
1449 :issue_to => Issue.find(7),
1456 :issue_to => Issue.find(7),
1450 :relation_type => IssueRelation::TYPE_PRECEDES)
1457 :relation_type => IssueRelation::TYPE_PRECEDES)
1451 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1458 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1452
1459
1453 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1460 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1454 end
1461 end
1455
1462
1456 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1463 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1457 IssueRelation.delete_all
1464 IssueRelation.delete_all
1458 assert IssueRelation.create!(:issue_from => Issue.find(1),
1465 assert IssueRelation.create!(:issue_from => Issue.find(1),
1459 :issue_to => Issue.find(2),
1466 :issue_to => Issue.find(2),
1460 :relation_type => IssueRelation::TYPE_RELATES)
1467 :relation_type => IssueRelation::TYPE_RELATES)
1461 assert IssueRelation.create!(:issue_from => Issue.find(2),
1468 assert IssueRelation.create!(:issue_from => Issue.find(2),
1462 :issue_to => Issue.find(3),
1469 :issue_to => Issue.find(3),
1463 :relation_type => IssueRelation::TYPE_RELATES)
1470 :relation_type => IssueRelation::TYPE_RELATES)
1464 assert IssueRelation.create!(:issue_from => Issue.find(3),
1471 assert IssueRelation.create!(:issue_from => Issue.find(3),
1465 :issue_to => Issue.find(8),
1472 :issue_to => Issue.find(8),
1466 :relation_type => IssueRelation::TYPE_RELATES)
1473 :relation_type => IssueRelation::TYPE_RELATES)
1467
1474
1468 r = IssueRelation.create!(:issue_from => Issue.find(8),
1475 r = IssueRelation.create!(:issue_from => Issue.find(8),
1469 :issue_to => Issue.find(7),
1476 :issue_to => Issue.find(7),
1470 :relation_type => IssueRelation::TYPE_RELATES)
1477 :relation_type => IssueRelation::TYPE_RELATES)
1471 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1478 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1472
1479
1473 r = IssueRelation.create!(:issue_from => Issue.find(3),
1480 r = IssueRelation.create!(:issue_from => Issue.find(3),
1474 :issue_to => Issue.find(7),
1481 :issue_to => Issue.find(7),
1475 :relation_type => IssueRelation::TYPE_RELATES)
1482 :relation_type => IssueRelation::TYPE_RELATES)
1476 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1483 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1477
1484
1478 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1485 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1479 end
1486 end
1480
1487
1481 context "#done_ratio" do
1488 context "#done_ratio" do
1482 setup do
1489 setup do
1483 @issue = Issue.find(1)
1490 @issue = Issue.find(1)
1484 @issue_status = IssueStatus.find(1)
1491 @issue_status = IssueStatus.find(1)
1485 @issue_status.update_attribute(:default_done_ratio, 50)
1492 @issue_status.update_attribute(:default_done_ratio, 50)
1486 @issue2 = Issue.find(2)
1493 @issue2 = Issue.find(2)
1487 @issue_status2 = IssueStatus.find(2)
1494 @issue_status2 = IssueStatus.find(2)
1488 @issue_status2.update_attribute(:default_done_ratio, 0)
1495 @issue_status2.update_attribute(:default_done_ratio, 0)
1489 end
1496 end
1490
1497
1491 teardown do
1498 teardown do
1492 Setting.issue_done_ratio = 'issue_field'
1499 Setting.issue_done_ratio = 'issue_field'
1493 end
1500 end
1494
1501
1495 context "with Setting.issue_done_ratio using the issue_field" do
1502 context "with Setting.issue_done_ratio using the issue_field" do
1496 setup do
1503 setup do
1497 Setting.issue_done_ratio = 'issue_field'
1504 Setting.issue_done_ratio = 'issue_field'
1498 end
1505 end
1499
1506
1500 should "read the issue's field" do
1507 should "read the issue's field" do
1501 assert_equal 0, @issue.done_ratio
1508 assert_equal 0, @issue.done_ratio
1502 assert_equal 30, @issue2.done_ratio
1509 assert_equal 30, @issue2.done_ratio
1503 end
1510 end
1504 end
1511 end
1505
1512
1506 context "with Setting.issue_done_ratio using the issue_status" do
1513 context "with Setting.issue_done_ratio using the issue_status" do
1507 setup do
1514 setup do
1508 Setting.issue_done_ratio = 'issue_status'
1515 Setting.issue_done_ratio = 'issue_status'
1509 end
1516 end
1510
1517
1511 should "read the Issue Status's default done ratio" do
1518 should "read the Issue Status's default done ratio" do
1512 assert_equal 50, @issue.done_ratio
1519 assert_equal 50, @issue.done_ratio
1513 assert_equal 0, @issue2.done_ratio
1520 assert_equal 0, @issue2.done_ratio
1514 end
1521 end
1515 end
1522 end
1516 end
1523 end
1517
1524
1518 context "#update_done_ratio_from_issue_status" do
1525 context "#update_done_ratio_from_issue_status" do
1519 setup do
1526 setup do
1520 @issue = Issue.find(1)
1527 @issue = Issue.find(1)
1521 @issue_status = IssueStatus.find(1)
1528 @issue_status = IssueStatus.find(1)
1522 @issue_status.update_attribute(:default_done_ratio, 50)
1529 @issue_status.update_attribute(:default_done_ratio, 50)
1523 @issue2 = Issue.find(2)
1530 @issue2 = Issue.find(2)
1524 @issue_status2 = IssueStatus.find(2)
1531 @issue_status2 = IssueStatus.find(2)
1525 @issue_status2.update_attribute(:default_done_ratio, 0)
1532 @issue_status2.update_attribute(:default_done_ratio, 0)
1526 end
1533 end
1527
1534
1528 context "with Setting.issue_done_ratio using the issue_field" do
1535 context "with Setting.issue_done_ratio using the issue_field" do
1529 setup do
1536 setup do
1530 Setting.issue_done_ratio = 'issue_field'
1537 Setting.issue_done_ratio = 'issue_field'
1531 end
1538 end
1532
1539
1533 should "not change the issue" do
1540 should "not change the issue" do
1534 @issue.update_done_ratio_from_issue_status
1541 @issue.update_done_ratio_from_issue_status
1535 @issue2.update_done_ratio_from_issue_status
1542 @issue2.update_done_ratio_from_issue_status
1536
1543
1537 assert_equal 0, @issue.read_attribute(:done_ratio)
1544 assert_equal 0, @issue.read_attribute(:done_ratio)
1538 assert_equal 30, @issue2.read_attribute(:done_ratio)
1545 assert_equal 30, @issue2.read_attribute(:done_ratio)
1539 end
1546 end
1540 end
1547 end
1541
1548
1542 context "with Setting.issue_done_ratio using the issue_status" do
1549 context "with Setting.issue_done_ratio using the issue_status" do
1543 setup do
1550 setup do
1544 Setting.issue_done_ratio = 'issue_status'
1551 Setting.issue_done_ratio = 'issue_status'
1545 end
1552 end
1546
1553
1547 should "change the issue's done ratio" do
1554 should "change the issue's done ratio" do
1548 @issue.update_done_ratio_from_issue_status
1555 @issue.update_done_ratio_from_issue_status
1549 @issue2.update_done_ratio_from_issue_status
1556 @issue2.update_done_ratio_from_issue_status
1550
1557
1551 assert_equal 50, @issue.read_attribute(:done_ratio)
1558 assert_equal 50, @issue.read_attribute(:done_ratio)
1552 assert_equal 0, @issue2.read_attribute(:done_ratio)
1559 assert_equal 0, @issue2.read_attribute(:done_ratio)
1553 end
1560 end
1554 end
1561 end
1555 end
1562 end
1556
1563
1557 test "#by_tracker" do
1564 test "#by_tracker" do
1558 User.current = User.anonymous
1565 User.current = User.anonymous
1559 groups = Issue.by_tracker(Project.find(1))
1566 groups = Issue.by_tracker(Project.find(1))
1560 assert_equal 3, groups.size
1567 assert_equal 3, groups.size
1561 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1568 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1562 end
1569 end
1563
1570
1564 test "#by_version" do
1571 test "#by_version" do
1565 User.current = User.anonymous
1572 User.current = User.anonymous
1566 groups = Issue.by_version(Project.find(1))
1573 groups = Issue.by_version(Project.find(1))
1567 assert_equal 3, groups.size
1574 assert_equal 3, groups.size
1568 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1575 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1569 end
1576 end
1570
1577
1571 test "#by_priority" do
1578 test "#by_priority" do
1572 User.current = User.anonymous
1579 User.current = User.anonymous
1573 groups = Issue.by_priority(Project.find(1))
1580 groups = Issue.by_priority(Project.find(1))
1574 assert_equal 4, groups.size
1581 assert_equal 4, groups.size
1575 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1582 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1576 end
1583 end
1577
1584
1578 test "#by_category" do
1585 test "#by_category" do
1579 User.current = User.anonymous
1586 User.current = User.anonymous
1580 groups = Issue.by_category(Project.find(1))
1587 groups = Issue.by_category(Project.find(1))
1581 assert_equal 2, groups.size
1588 assert_equal 2, groups.size
1582 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1589 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1583 end
1590 end
1584
1591
1585 test "#by_assigned_to" do
1592 test "#by_assigned_to" do
1586 User.current = User.anonymous
1593 User.current = User.anonymous
1587 groups = Issue.by_assigned_to(Project.find(1))
1594 groups = Issue.by_assigned_to(Project.find(1))
1588 assert_equal 2, groups.size
1595 assert_equal 2, groups.size
1589 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1596 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1590 end
1597 end
1591
1598
1592 test "#by_author" do
1599 test "#by_author" do
1593 User.current = User.anonymous
1600 User.current = User.anonymous
1594 groups = Issue.by_author(Project.find(1))
1601 groups = Issue.by_author(Project.find(1))
1595 assert_equal 4, groups.size
1602 assert_equal 4, groups.size
1596 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1603 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1597 end
1604 end
1598
1605
1599 test "#by_subproject" do
1606 test "#by_subproject" do
1600 User.current = User.anonymous
1607 User.current = User.anonymous
1601 groups = Issue.by_subproject(Project.find(1))
1608 groups = Issue.by_subproject(Project.find(1))
1602 # Private descendant not visible
1609 # Private descendant not visible
1603 assert_equal 1, groups.size
1610 assert_equal 1, groups.size
1604 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1611 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1605 end
1612 end
1606
1613
1607 def test_recently_updated_scope
1614 def test_recently_updated_scope
1608 #should return the last updated issue
1615 #should return the last updated issue
1609 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1616 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1610 end
1617 end
1611
1618
1612 def test_on_active_projects_scope
1619 def test_on_active_projects_scope
1613 assert Project.find(2).archive
1620 assert Project.find(2).archive
1614
1621
1615 before = Issue.on_active_project.length
1622 before = Issue.on_active_project.length
1616 # test inclusion to results
1623 # test inclusion to results
1617 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1624 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1618 assert_equal before + 1, Issue.on_active_project.length
1625 assert_equal before + 1, Issue.on_active_project.length
1619
1626
1620 # Move to an archived project
1627 # Move to an archived project
1621 issue.project = Project.find(2)
1628 issue.project = Project.find(2)
1622 assert issue.save
1629 assert issue.save
1623 assert_equal before, Issue.on_active_project.length
1630 assert_equal before, Issue.on_active_project.length
1624 end
1631 end
1625
1632
1626 context "Issue#recipients" do
1633 context "Issue#recipients" do
1627 setup do
1634 setup do
1628 @project = Project.find(1)
1635 @project = Project.find(1)
1629 @author = User.generate!
1636 @author = User.generate!
1630 @assignee = User.generate!
1637 @assignee = User.generate!
1631 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1638 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1632 end
1639 end
1633
1640
1634 should "include project recipients" do
1641 should "include project recipients" do
1635 assert @project.recipients.present?
1642 assert @project.recipients.present?
1636 @project.recipients.each do |project_recipient|
1643 @project.recipients.each do |project_recipient|
1637 assert @issue.recipients.include?(project_recipient)
1644 assert @issue.recipients.include?(project_recipient)
1638 end
1645 end
1639 end
1646 end
1640
1647
1641 should "include the author if the author is active" do
1648 should "include the author if the author is active" do
1642 assert @issue.author, "No author set for Issue"
1649 assert @issue.author, "No author set for Issue"
1643 assert @issue.recipients.include?(@issue.author.mail)
1650 assert @issue.recipients.include?(@issue.author.mail)
1644 end
1651 end
1645
1652
1646 should "include the assigned to user if the assigned to user is active" do
1653 should "include the assigned to user if the assigned to user is active" do
1647 assert @issue.assigned_to, "No assigned_to set for Issue"
1654 assert @issue.assigned_to, "No assigned_to set for Issue"
1648 assert @issue.recipients.include?(@issue.assigned_to.mail)
1655 assert @issue.recipients.include?(@issue.assigned_to.mail)
1649 end
1656 end
1650
1657
1651 should "not include users who opt out of all email" do
1658 should "not include users who opt out of all email" do
1652 @author.update_attribute(:mail_notification, :none)
1659 @author.update_attribute(:mail_notification, :none)
1653
1660
1654 assert !@issue.recipients.include?(@issue.author.mail)
1661 assert !@issue.recipients.include?(@issue.author.mail)
1655 end
1662 end
1656
1663
1657 should "not include the issue author if they are only notified of assigned issues" do
1664 should "not include the issue author if they are only notified of assigned issues" do
1658 @author.update_attribute(:mail_notification, :only_assigned)
1665 @author.update_attribute(:mail_notification, :only_assigned)
1659
1666
1660 assert !@issue.recipients.include?(@issue.author.mail)
1667 assert !@issue.recipients.include?(@issue.author.mail)
1661 end
1668 end
1662
1669
1663 should "not include the assigned user if they are only notified of owned issues" do
1670 should "not include the assigned user if they are only notified of owned issues" do
1664 @assignee.update_attribute(:mail_notification, :only_owner)
1671 @assignee.update_attribute(:mail_notification, :only_owner)
1665
1672
1666 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1673 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1667 end
1674 end
1668 end
1675 end
1669
1676
1670 def test_last_journal_id_with_journals_should_return_the_journal_id
1677 def test_last_journal_id_with_journals_should_return_the_journal_id
1671 assert_equal 2, Issue.find(1).last_journal_id
1678 assert_equal 2, Issue.find(1).last_journal_id
1672 end
1679 end
1673
1680
1674 def test_last_journal_id_without_journals_should_return_nil
1681 def test_last_journal_id_without_journals_should_return_nil
1675 assert_nil Issue.find(3).last_journal_id
1682 assert_nil Issue.find(3).last_journal_id
1676 end
1683 end
1677
1684
1678 def test_journals_after_should_return_journals_with_greater_id
1685 def test_journals_after_should_return_journals_with_greater_id
1679 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1686 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1680 assert_equal [], Issue.find(1).journals_after('2')
1687 assert_equal [], Issue.find(1).journals_after('2')
1681 end
1688 end
1682
1689
1683 def test_journals_after_with_blank_arg_should_return_all_journals
1690 def test_journals_after_with_blank_arg_should_return_all_journals
1684 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1691 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1685 end
1692 end
1686 end
1693 end
General Comments 0
You need to be logged in to leave comments. Login now