##// END OF EJS Templates
code layout clean up test_required_attributes_should_be_validated of unit issue test...
Toshi MARUYAMA -
r10435:93daf6865ed5
parent child
Show More
@@ -1,1756 +1,1772
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,
341 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
342 :status_id => 1, :subject => 'Test',
342 :status_id => 1, :subject => 'Test',
343 :custom_field_values => {'2' => 'Test'})
343 :custom_field_values => {'2' => 'Test'})
344 assert !Tracker.find(2).custom_field_ids.include?(2)
344 assert !Tracker.find(2).custom_field_ids.include?(2)
345
345
346 issue = Issue.find(issue.id)
346 issue = Issue.find(issue.id)
347 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
347 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
348
348
349 issue = Issue.find(issue.id)
349 issue = Issue.find(issue.id)
350 custom_value = issue.custom_value_for(2)
350 custom_value = issue.custom_value_for(2)
351 assert_not_nil custom_value
351 assert_not_nil custom_value
352 assert_equal 'Test', custom_value.value
352 assert_equal 'Test', custom_value.value
353 end
353 end
354
354
355 def test_assigning_tracker_id_should_reload_custom_fields_values
355 def test_assigning_tracker_id_should_reload_custom_fields_values
356 issue = Issue.new(:project => Project.find(1))
356 issue = Issue.new(:project => Project.find(1))
357 assert issue.custom_field_values.empty?
357 assert issue.custom_field_values.empty?
358 issue.tracker_id = 1
358 issue.tracker_id = 1
359 assert issue.custom_field_values.any?
359 assert issue.custom_field_values.any?
360 end
360 end
361
361
362 def test_assigning_attributes_should_assign_project_and_tracker_first
362 def test_assigning_attributes_should_assign_project_and_tracker_first
363 seq = sequence('seq')
363 seq = sequence('seq')
364 issue = Issue.new
364 issue = Issue.new
365 issue.expects(:project_id=).in_sequence(seq)
365 issue.expects(:project_id=).in_sequence(seq)
366 issue.expects(:tracker_id=).in_sequence(seq)
366 issue.expects(:tracker_id=).in_sequence(seq)
367 issue.expects(:subject=).in_sequence(seq)
367 issue.expects(:subject=).in_sequence(seq)
368 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
368 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
369 end
369 end
370
370
371 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
371 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
372 attributes = ActiveSupport::OrderedHash.new
372 attributes = ActiveSupport::OrderedHash.new
373 attributes['custom_field_values'] = { '1' => 'MySQL' }
373 attributes['custom_field_values'] = { '1' => 'MySQL' }
374 attributes['tracker_id'] = '1'
374 attributes['tracker_id'] = '1'
375 issue = Issue.new(:project => Project.find(1))
375 issue = Issue.new(:project => Project.find(1))
376 issue.attributes = attributes
376 issue.attributes = attributes
377 assert_equal 'MySQL', issue.custom_field_value(1)
377 assert_equal 'MySQL', issue.custom_field_value(1)
378 end
378 end
379
379
380 def test_should_update_issue_with_disabled_tracker
380 def test_should_update_issue_with_disabled_tracker
381 p = Project.find(1)
381 p = Project.find(1)
382 issue = Issue.find(1)
382 issue = Issue.find(1)
383
383
384 p.trackers.delete(issue.tracker)
384 p.trackers.delete(issue.tracker)
385 assert !p.trackers.include?(issue.tracker)
385 assert !p.trackers.include?(issue.tracker)
386
386
387 issue.reload
387 issue.reload
388 issue.subject = 'New subject'
388 issue.subject = 'New subject'
389 assert issue.save
389 assert issue.save
390 end
390 end
391
391
392 def test_should_not_set_a_disabled_tracker
392 def test_should_not_set_a_disabled_tracker
393 p = Project.find(1)
393 p = Project.find(1)
394 p.trackers.delete(Tracker.find(2))
394 p.trackers.delete(Tracker.find(2))
395
395
396 issue = Issue.find(1)
396 issue = Issue.find(1)
397 issue.tracker_id = 2
397 issue.tracker_id = 2
398 issue.subject = 'New subject'
398 issue.subject = 'New subject'
399 assert !issue.save
399 assert !issue.save
400 assert_not_nil issue.errors[:tracker_id]
400 assert_not_nil issue.errors[:tracker_id]
401 end
401 end
402
402
403 def test_category_based_assignment
403 def test_category_based_assignment
404 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
404 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
405 :status_id => 1, :priority => IssuePriority.all.first,
405 :status_id => 1, :priority => IssuePriority.all.first,
406 :subject => 'Assignment test',
406 :subject => 'Assignment test',
407 :description => 'Assignment test', :category_id => 1)
407 :description => 'Assignment test', :category_id => 1)
408 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
408 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
409 end
409 end
410
410
411 def test_new_statuses_allowed_to
411 def test_new_statuses_allowed_to
412 WorkflowTransition.delete_all
412 WorkflowTransition.delete_all
413 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
413 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
414 :old_status_id => 1, :new_status_id => 2,
414 :old_status_id => 1, :new_status_id => 2,
415 :author => false, :assignee => false)
415 :author => false, :assignee => false)
416 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
416 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
417 :old_status_id => 1, :new_status_id => 3,
417 :old_status_id => 1, :new_status_id => 3,
418 :author => true, :assignee => false)
418 :author => true, :assignee => false)
419 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1,
419 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1,
420 :new_status_id => 4, :author => false,
420 :new_status_id => 4, :author => false,
421 :assignee => true)
421 :assignee => true)
422 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
422 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
423 :old_status_id => 1, :new_status_id => 5,
423 :old_status_id => 1, :new_status_id => 5,
424 :author => true, :assignee => true)
424 :author => true, :assignee => true)
425 status = IssueStatus.find(1)
425 status = IssueStatus.find(1)
426 role = Role.find(1)
426 role = Role.find(1)
427 tracker = Tracker.find(1)
427 tracker = Tracker.find(1)
428 user = User.find(2)
428 user = User.find(2)
429
429
430 issue = Issue.generate!(:tracker => tracker, :status => status,
430 issue = Issue.generate!(:tracker => tracker, :status => status,
431 :project_id => 1, :author_id => 1)
431 :project_id => 1, :author_id => 1)
432 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
432 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
433
433
434 issue = Issue.generate!(:tracker => tracker, :status => status,
434 issue = Issue.generate!(:tracker => tracker, :status => status,
435 :project_id => 1, :author => user)
435 :project_id => 1, :author => user)
436 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
436 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
437
437
438 issue = Issue.generate!(:tracker => tracker, :status => status,
438 issue = Issue.generate!(:tracker => tracker, :status => status,
439 :project_id => 1, :author_id => 1,
439 :project_id => 1, :author_id => 1,
440 :assigned_to => user)
440 :assigned_to => user)
441 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
441 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
442
442
443 issue = Issue.generate!(:tracker => tracker, :status => status,
443 issue = Issue.generate!(:tracker => tracker, :status => status,
444 :project_id => 1, :author => user,
444 :project_id => 1, :author => user,
445 :assigned_to => user)
445 :assigned_to => user)
446 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
446 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
447 end
447 end
448
448
449 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
449 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
450 admin = User.find(1)
450 admin = User.find(1)
451 issue = Issue.find(1)
451 issue = Issue.find(1)
452 assert !admin.member_of?(issue.project)
452 assert !admin.member_of?(issue.project)
453 expected_statuses = [issue.status] +
453 expected_statuses = [issue.status] +
454 WorkflowTransition.find_all_by_old_status_id(
454 WorkflowTransition.find_all_by_old_status_id(
455 issue.status_id).map(&:new_status).uniq.sort
455 issue.status_id).map(&:new_status).uniq.sort
456 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
456 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
457 end
457 end
458
458
459 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
459 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
460 issue = Issue.find(1).copy
460 issue = Issue.find(1).copy
461 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
461 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
462
462
463 issue = Issue.find(2).copy
463 issue = Issue.find(2).copy
464 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
464 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
465 end
465 end
466
466
467 def test_safe_attributes_names_should_not_include_disabled_field
467 def test_safe_attributes_names_should_not_include_disabled_field
468 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
468 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
469
469
470 issue = Issue.new(:tracker => tracker)
470 issue = Issue.new(:tracker => tracker)
471 assert_include 'tracker_id', issue.safe_attribute_names
471 assert_include 'tracker_id', issue.safe_attribute_names
472 assert_include 'status_id', issue.safe_attribute_names
472 assert_include 'status_id', issue.safe_attribute_names
473 assert_include 'subject', issue.safe_attribute_names
473 assert_include 'subject', issue.safe_attribute_names
474 assert_include 'description', issue.safe_attribute_names
474 assert_include 'description', issue.safe_attribute_names
475 assert_include 'custom_field_values', issue.safe_attribute_names
475 assert_include 'custom_field_values', issue.safe_attribute_names
476 assert_include 'custom_fields', issue.safe_attribute_names
476 assert_include 'custom_fields', issue.safe_attribute_names
477 assert_include 'lock_version', issue.safe_attribute_names
477 assert_include 'lock_version', issue.safe_attribute_names
478
478
479 tracker.core_fields.each do |field|
479 tracker.core_fields.each do |field|
480 assert_include field, issue.safe_attribute_names
480 assert_include field, issue.safe_attribute_names
481 end
481 end
482
482
483 tracker.disabled_core_fields.each do |field|
483 tracker.disabled_core_fields.each do |field|
484 assert_not_include field, issue.safe_attribute_names
484 assert_not_include field, issue.safe_attribute_names
485 end
485 end
486 end
486 end
487
487
488 def test_safe_attributes_should_ignore_disabled_fields
488 def test_safe_attributes_should_ignore_disabled_fields
489 tracker = Tracker.find(1)
489 tracker = Tracker.find(1)
490 tracker.core_fields = %w(assigned_to_id due_date)
490 tracker.core_fields = %w(assigned_to_id due_date)
491 tracker.save!
491 tracker.save!
492
492
493 issue = Issue.new(:tracker => tracker)
493 issue = Issue.new(:tracker => tracker)
494 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
494 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
495 assert_nil issue.start_date
495 assert_nil issue.start_date
496 assert_equal Date.parse('2012-07-14'), issue.due_date
496 assert_equal Date.parse('2012-07-14'), issue.due_date
497 end
497 end
498
498
499 def test_safe_attributes_should_accept_target_tracker_enabled_fields
499 def test_safe_attributes_should_accept_target_tracker_enabled_fields
500 source = Tracker.find(1)
500 source = Tracker.find(1)
501 source.core_fields = []
501 source.core_fields = []
502 source.save!
502 source.save!
503 target = Tracker.find(2)
503 target = Tracker.find(2)
504 target.core_fields = %w(assigned_to_id due_date)
504 target.core_fields = %w(assigned_to_id due_date)
505 target.save!
505 target.save!
506
506
507 issue = Issue.new(:tracker => source)
507 issue = Issue.new(:tracker => source)
508 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
508 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
509 assert_equal target, issue.tracker
509 assert_equal target, issue.tracker
510 assert_equal Date.parse('2012-07-14'), issue.due_date
510 assert_equal Date.parse('2012-07-14'), issue.due_date
511 end
511 end
512
512
513 def test_safe_attributes_should_not_include_readonly_fields
513 def test_safe_attributes_should_not_include_readonly_fields
514 WorkflowPermission.delete_all
514 WorkflowPermission.delete_all
515 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
515 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
516 :role_id => 1, :field_name => 'due_date',
516 :role_id => 1, :field_name => 'due_date',
517 :rule => 'readonly')
517 :rule => 'readonly')
518 user = User.find(2)
518 user = User.find(2)
519
519
520 issue = Issue.new(:project_id => 1, :tracker_id => 1)
520 issue = Issue.new(:project_id => 1, :tracker_id => 1)
521 assert_equal %w(due_date), issue.read_only_attribute_names(user)
521 assert_equal %w(due_date), issue.read_only_attribute_names(user)
522 assert_not_include 'due_date', issue.safe_attribute_names(user)
522 assert_not_include 'due_date', issue.safe_attribute_names(user)
523
523
524 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
524 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
525 assert_equal Date.parse('2012-07-14'), issue.start_date
525 assert_equal Date.parse('2012-07-14'), issue.start_date
526 assert_nil issue.due_date
526 assert_nil issue.due_date
527 end
527 end
528
528
529 def test_safe_attributes_should_not_include_readonly_custom_fields
529 def test_safe_attributes_should_not_include_readonly_custom_fields
530 cf1 = IssueCustomField.create!(:name => 'Writable field',
530 cf1 = IssueCustomField.create!(:name => 'Writable field',
531 :field_format => 'string',
531 :field_format => 'string',
532 :is_for_all => true, :tracker_ids => [1])
532 :is_for_all => true, :tracker_ids => [1])
533 cf2 = IssueCustomField.create!(:name => 'Readonly field',
533 cf2 = IssueCustomField.create!(:name => 'Readonly field',
534 :field_format => 'string',
534 :field_format => 'string',
535 :is_for_all => true, :tracker_ids => [1])
535 :is_for_all => true, :tracker_ids => [1])
536 WorkflowPermission.delete_all
536 WorkflowPermission.delete_all
537 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
537 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
538 :role_id => 1, :field_name => cf2.id.to_s,
538 :role_id => 1, :field_name => cf2.id.to_s,
539 :rule => 'readonly')
539 :rule => 'readonly')
540 user = User.find(2)
540 user = User.find(2)
541 issue = Issue.new(:project_id => 1, :tracker_id => 1)
541 issue = Issue.new(:project_id => 1, :tracker_id => 1)
542 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
542 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
543 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
543 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
544
544
545 issue.send :safe_attributes=, {'custom_field_values' => {
545 issue.send :safe_attributes=, {'custom_field_values' => {
546 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
546 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
547 }}, user
547 }}, user
548 assert_equal 'value1', issue.custom_field_value(cf1)
548 assert_equal 'value1', issue.custom_field_value(cf1)
549 assert_nil issue.custom_field_value(cf2)
549 assert_nil issue.custom_field_value(cf2)
550
550
551 issue.send :safe_attributes=, {'custom_fields' => [
551 issue.send :safe_attributes=, {'custom_fields' => [
552 {'id' => cf1.id.to_s, 'value' => 'valuea'},
552 {'id' => cf1.id.to_s, 'value' => 'valuea'},
553 {'id' => cf2.id.to_s, 'value' => 'valueb'}
553 {'id' => cf2.id.to_s, 'value' => 'valueb'}
554 ]}, user
554 ]}, user
555 assert_equal 'valuea', issue.custom_field_value(cf1)
555 assert_equal 'valuea', issue.custom_field_value(cf1)
556 assert_nil issue.custom_field_value(cf2)
556 assert_nil issue.custom_field_value(cf2)
557 end
557 end
558
558
559 def test_editable_custom_field_values_should_return_non_readonly_custom_values
559 def test_editable_custom_field_values_should_return_non_readonly_custom_values
560 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
560 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
561 :is_for_all => true, :tracker_ids => [1, 2])
561 :is_for_all => true, :tracker_ids => [1, 2])
562 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
562 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
563 :is_for_all => true, :tracker_ids => [1, 2])
563 :is_for_all => true, :tracker_ids => [1, 2])
564 WorkflowPermission.delete_all
564 WorkflowPermission.delete_all
565 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
565 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
566 :field_name => cf2.id.to_s, :rule => 'readonly')
566 :field_name => cf2.id.to_s, :rule => 'readonly')
567 user = User.find(2)
567 user = User.find(2)
568
568
569 issue = Issue.new(:project_id => 1, :tracker_id => 1)
569 issue = Issue.new(:project_id => 1, :tracker_id => 1)
570 values = issue.editable_custom_field_values(user)
570 values = issue.editable_custom_field_values(user)
571 assert values.detect {|value| value.custom_field == cf1}
571 assert values.detect {|value| value.custom_field == cf1}
572 assert_nil values.detect {|value| value.custom_field == cf2}
572 assert_nil values.detect {|value| value.custom_field == cf2}
573
573
574 issue.tracker_id = 2
574 issue.tracker_id = 2
575 values = issue.editable_custom_field_values(user)
575 values = issue.editable_custom_field_values(user)
576 assert values.detect {|value| value.custom_field == cf1}
576 assert values.detect {|value| value.custom_field == cf1}
577 assert values.detect {|value| value.custom_field == cf2}
577 assert values.detect {|value| value.custom_field == cf2}
578 end
578 end
579
579
580 def test_safe_attributes_should_accept_target_tracker_writable_fields
580 def test_safe_attributes_should_accept_target_tracker_writable_fields
581 WorkflowPermission.delete_all
581 WorkflowPermission.delete_all
582 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
582 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
583 :role_id => 1, :field_name => 'due_date',
583 :role_id => 1, :field_name => 'due_date',
584 :rule => 'readonly')
584 :rule => 'readonly')
585 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
585 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
586 :role_id => 1, :field_name => 'start_date',
586 :role_id => 1, :field_name => 'start_date',
587 :rule => 'readonly')
587 :rule => 'readonly')
588 user = User.find(2)
588 user = User.find(2)
589
589
590 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
590 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
591
591
592 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
592 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
593 'due_date' => '2012-07-14'}, user
593 'due_date' => '2012-07-14'}, user
594 assert_equal Date.parse('2012-07-12'), issue.start_date
594 assert_equal Date.parse('2012-07-12'), issue.start_date
595 assert_nil issue.due_date
595 assert_nil issue.due_date
596
596
597 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
597 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
598 'due_date' => '2012-07-16',
598 'due_date' => '2012-07-16',
599 'tracker_id' => 2}, user
599 'tracker_id' => 2}, user
600 assert_equal Date.parse('2012-07-12'), issue.start_date
600 assert_equal Date.parse('2012-07-12'), issue.start_date
601 assert_equal Date.parse('2012-07-16'), issue.due_date
601 assert_equal Date.parse('2012-07-16'), issue.due_date
602 end
602 end
603
603
604 def test_safe_attributes_should_accept_target_status_writable_fields
604 def test_safe_attributes_should_accept_target_status_writable_fields
605 WorkflowPermission.delete_all
605 WorkflowPermission.delete_all
606 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
606 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
607 :role_id => 1, :field_name => 'due_date',
607 :role_id => 1, :field_name => 'due_date',
608 :rule => 'readonly')
608 :rule => 'readonly')
609 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
609 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
610 :role_id => 1, :field_name => 'start_date',
610 :role_id => 1, :field_name => 'start_date',
611 :rule => 'readonly')
611 :rule => 'readonly')
612 user = User.find(2)
612 user = User.find(2)
613
613
614 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
614 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
615
615
616 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
616 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
617 'due_date' => '2012-07-14'},
617 'due_date' => '2012-07-14'},
618 user
618 user
619 assert_equal Date.parse('2012-07-12'), issue.start_date
619 assert_equal Date.parse('2012-07-12'), issue.start_date
620 assert_nil issue.due_date
620 assert_nil issue.due_date
621
621
622 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
622 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
623 'due_date' => '2012-07-16',
623 'due_date' => '2012-07-16',
624 'status_id' => 2},
624 'status_id' => 2},
625 user
625 user
626 assert_equal Date.parse('2012-07-12'), issue.start_date
626 assert_equal Date.parse('2012-07-12'), issue.start_date
627 assert_equal Date.parse('2012-07-16'), issue.due_date
627 assert_equal Date.parse('2012-07-16'), issue.due_date
628 end
628 end
629
629
630 def test_required_attributes_should_be_validated
630 def test_required_attributes_should_be_validated
631 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
631 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
632 :is_for_all => true, :tracker_ids => [1, 2])
632
633
633 WorkflowPermission.delete_all
634 WorkflowPermission.delete_all
634 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
635 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
635 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'category_id', :rule => 'required')
636 :role_id => 1, :field_name => 'due_date',
636 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf.id.to_s, :rule => 'required')
637 :rule => 'required')
638 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
639 :role_id => 1, :field_name => 'category_id',
640 :rule => 'required')
641 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
642 :role_id => 1, :field_name => cf.id.to_s,
643 :rule => 'required')
637
644
638 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'start_date', :rule => 'required')
645 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
639 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf.id.to_s, :rule => 'required')
646 :role_id => 1, :field_name => 'start_date',
647 :rule => 'required')
648 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
649 :role_id => 1, :field_name => cf.id.to_s,
650 :rule => 'required')
640 user = User.find(2)
651 user = User.find(2)
641
652
642 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Required fields', :author => user)
653 issue = Issue.new(:project_id => 1, :tracker_id => 1,
643 assert_equal [cf.id.to_s, "category_id", "due_date"], issue.required_attribute_names(user).sort
654 :status_id => 1, :subject => 'Required fields',
655 :author => user)
656 assert_equal [cf.id.to_s, "category_id", "due_date"],
657 issue.required_attribute_names(user).sort
644 assert !issue.save, "Issue was saved"
658 assert !issue.save, "Issue was saved"
645 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"], issue.errors.full_messages.sort
659 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
660 issue.errors.full_messages.sort
646
661
647 issue.tracker_id = 2
662 issue.tracker_id = 2
648 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
663 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
649 assert !issue.save, "Issue was saved"
664 assert !issue.save, "Issue was saved"
650 assert_equal ["Foo can't be blank", "Start date can't be blank"], issue.errors.full_messages.sort
665 assert_equal ["Foo can't be blank", "Start date can't be blank"],
666 issue.errors.full_messages.sort
651
667
652 issue.start_date = Date.today
668 issue.start_date = Date.today
653 issue.custom_field_values = {cf.id.to_s => 'bar'}
669 issue.custom_field_values = {cf.id.to_s => 'bar'}
654 assert issue.save
670 assert issue.save
655 end
671 end
656
672
657 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
673 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
658 WorkflowPermission.delete_all
674 WorkflowPermission.delete_all
659 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
660 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'required')
676 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'required')
661 user = User.find(2)
677 user = User.find(2)
662 member = Member.find(1)
678 member = Member.find(1)
663 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
679 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
664
680
665 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
681 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
666
682
667 member.role_ids = [1, 2]
683 member.role_ids = [1, 2]
668 member.save!
684 member.save!
669 assert_equal [], issue.required_attribute_names(user.reload)
685 assert_equal [], issue.required_attribute_names(user.reload)
670
686
671 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'required')
687 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'required')
672 assert_equal %w(due_date), issue.required_attribute_names(user)
688 assert_equal %w(due_date), issue.required_attribute_names(user)
673
689
674 member.role_ids = [1, 2, 3]
690 member.role_ids = [1, 2, 3]
675 member.save!
691 member.save!
676 assert_equal [], issue.required_attribute_names(user.reload)
692 assert_equal [], issue.required_attribute_names(user.reload)
677
693
678 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
694 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
679 # required + readonly => required
695 # required + readonly => required
680 assert_equal %w(due_date), issue.required_attribute_names(user)
696 assert_equal %w(due_date), issue.required_attribute_names(user)
681 end
697 end
682
698
683 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
699 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
684 WorkflowPermission.delete_all
700 WorkflowPermission.delete_all
685 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
701 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
686 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
702 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'start_date', :rule => 'readonly')
687 user = User.find(2)
703 user = User.find(2)
688 member = Member.find(1)
704 member = Member.find(1)
689 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
705 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
690
706
691 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
707 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
692
708
693 member.role_ids = [1, 2]
709 member.role_ids = [1, 2]
694 member.save!
710 member.save!
695 assert_equal [], issue.read_only_attribute_names(user.reload)
711 assert_equal [], issue.read_only_attribute_names(user.reload)
696
712
697 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
713 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 2, :field_name => 'due_date', :rule => 'readonly')
698 assert_equal %w(due_date), issue.read_only_attribute_names(user)
714 assert_equal %w(due_date), issue.read_only_attribute_names(user)
699 end
715 end
700
716
701 def test_copy
717 def test_copy
702 issue = Issue.new.copy_from(1)
718 issue = Issue.new.copy_from(1)
703 assert issue.copy?
719 assert issue.copy?
704 assert issue.save
720 assert issue.save
705 issue.reload
721 issue.reload
706 orig = Issue.find(1)
722 orig = Issue.find(1)
707 assert_equal orig.subject, issue.subject
723 assert_equal orig.subject, issue.subject
708 assert_equal orig.tracker, issue.tracker
724 assert_equal orig.tracker, issue.tracker
709 assert_equal "125", issue.custom_value_for(2).value
725 assert_equal "125", issue.custom_value_for(2).value
710 end
726 end
711
727
712 def test_copy_should_copy_status
728 def test_copy_should_copy_status
713 orig = Issue.find(8)
729 orig = Issue.find(8)
714 assert orig.status != IssueStatus.default
730 assert orig.status != IssueStatus.default
715
731
716 issue = Issue.new.copy_from(orig)
732 issue = Issue.new.copy_from(orig)
717 assert issue.save
733 assert issue.save
718 issue.reload
734 issue.reload
719 assert_equal orig.status, issue.status
735 assert_equal orig.status, issue.status
720 end
736 end
721
737
722 def test_copy_should_add_relation_with_copied_issue
738 def test_copy_should_add_relation_with_copied_issue
723 copied = Issue.find(1)
739 copied = Issue.find(1)
724 issue = Issue.new.copy_from(copied)
740 issue = Issue.new.copy_from(copied)
725 assert issue.save
741 assert issue.save
726 issue.reload
742 issue.reload
727
743
728 assert_equal 1, issue.relations.size
744 assert_equal 1, issue.relations.size
729 relation = issue.relations.first
745 relation = issue.relations.first
730 assert_equal 'copied_to', relation.relation_type
746 assert_equal 'copied_to', relation.relation_type
731 assert_equal copied, relation.issue_from
747 assert_equal copied, relation.issue_from
732 assert_equal issue, relation.issue_to
748 assert_equal issue, relation.issue_to
733 end
749 end
734
750
735 def test_copy_should_copy_subtasks
751 def test_copy_should_copy_subtasks
736 issue = Issue.generate_with_descendants!
752 issue = Issue.generate_with_descendants!
737
753
738 copy = issue.reload.copy
754 copy = issue.reload.copy
739 copy.author = User.find(7)
755 copy.author = User.find(7)
740 assert_difference 'Issue.count', 1+issue.descendants.count do
756 assert_difference 'Issue.count', 1+issue.descendants.count do
741 assert copy.save
757 assert copy.save
742 end
758 end
743 copy.reload
759 copy.reload
744 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
760 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
745 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
761 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
746 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
762 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
747 assert_equal copy.author, child_copy.author
763 assert_equal copy.author, child_copy.author
748 end
764 end
749
765
750 def test_copy_should_copy_subtasks_to_target_project
766 def test_copy_should_copy_subtasks_to_target_project
751 issue = Issue.generate_with_descendants!
767 issue = Issue.generate_with_descendants!
752
768
753 copy = issue.copy(:project_id => 3)
769 copy = issue.copy(:project_id => 3)
754 assert_difference 'Issue.count', 1+issue.descendants.count do
770 assert_difference 'Issue.count', 1+issue.descendants.count do
755 assert copy.save
771 assert copy.save
756 end
772 end
757 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
773 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
758 end
774 end
759
775
760 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
776 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
761 issue = Issue.generate_with_descendants!
777 issue = Issue.generate_with_descendants!
762
778
763 copy = issue.reload.copy
779 copy = issue.reload.copy
764 assert_difference 'Issue.count', 1+issue.descendants.count do
780 assert_difference 'Issue.count', 1+issue.descendants.count do
765 assert copy.save
781 assert copy.save
766 assert copy.save
782 assert copy.save
767 end
783 end
768 end
784 end
769
785
770 def test_should_not_call_after_project_change_on_creation
786 def test_should_not_call_after_project_change_on_creation
771 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Test', :author_id => 1)
787 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Test', :author_id => 1)
772 issue.expects(:after_project_change).never
788 issue.expects(:after_project_change).never
773 issue.save!
789 issue.save!
774 end
790 end
775
791
776 def test_should_not_call_after_project_change_on_update
792 def test_should_not_call_after_project_change_on_update
777 issue = Issue.find(1)
793 issue = Issue.find(1)
778 issue.project = Project.find(1)
794 issue.project = Project.find(1)
779 issue.subject = 'No project change'
795 issue.subject = 'No project change'
780 issue.expects(:after_project_change).never
796 issue.expects(:after_project_change).never
781 issue.save!
797 issue.save!
782 end
798 end
783
799
784 def test_should_call_after_project_change_on_project_change
800 def test_should_call_after_project_change_on_project_change
785 issue = Issue.find(1)
801 issue = Issue.find(1)
786 issue.project = Project.find(2)
802 issue.project = Project.find(2)
787 issue.expects(:after_project_change).once
803 issue.expects(:after_project_change).once
788 issue.save!
804 issue.save!
789 end
805 end
790
806
791 def test_adding_journal_should_update_timestamp
807 def test_adding_journal_should_update_timestamp
792 issue = Issue.find(1)
808 issue = Issue.find(1)
793 updated_on_was = issue.updated_on
809 updated_on_was = issue.updated_on
794
810
795 issue.init_journal(User.first, "Adding notes")
811 issue.init_journal(User.first, "Adding notes")
796 assert_difference 'Journal.count' do
812 assert_difference 'Journal.count' do
797 assert issue.save
813 assert issue.save
798 end
814 end
799 issue.reload
815 issue.reload
800
816
801 assert_not_equal updated_on_was, issue.updated_on
817 assert_not_equal updated_on_was, issue.updated_on
802 end
818 end
803
819
804 def test_should_close_duplicates
820 def test_should_close_duplicates
805 # Create 3 issues
821 # Create 3 issues
806 issue1 = Issue.generate!
822 issue1 = Issue.generate!
807 issue2 = Issue.generate!
823 issue2 = Issue.generate!
808 issue3 = Issue.generate!
824 issue3 = Issue.generate!
809
825
810 # 2 is a dupe of 1
826 # 2 is a dupe of 1
811 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
827 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
812 # And 3 is a dupe of 2
828 # And 3 is a dupe of 2
813 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
829 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
814 # And 3 is a dupe of 1 (circular duplicates)
830 # And 3 is a dupe of 1 (circular duplicates)
815 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
831 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
816
832
817 assert issue1.reload.duplicates.include?(issue2)
833 assert issue1.reload.duplicates.include?(issue2)
818
834
819 # Closing issue 1
835 # Closing issue 1
820 issue1.init_journal(User.find(:first), "Closing issue1")
836 issue1.init_journal(User.find(:first), "Closing issue1")
821 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
837 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
822 assert issue1.save
838 assert issue1.save
823 # 2 and 3 should be also closed
839 # 2 and 3 should be also closed
824 assert issue2.reload.closed?
840 assert issue2.reload.closed?
825 assert issue3.reload.closed?
841 assert issue3.reload.closed?
826 end
842 end
827
843
828 def test_should_not_close_duplicated_issue
844 def test_should_not_close_duplicated_issue
829 issue1 = Issue.generate!
845 issue1 = Issue.generate!
830 issue2 = Issue.generate!
846 issue2 = Issue.generate!
831
847
832 # 2 is a dupe of 1
848 # 2 is a dupe of 1
833 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
849 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
834 # 2 is a dup of 1 but 1 is not a duplicate of 2
850 # 2 is a dup of 1 but 1 is not a duplicate of 2
835 assert !issue2.reload.duplicates.include?(issue1)
851 assert !issue2.reload.duplicates.include?(issue1)
836
852
837 # Closing issue 2
853 # Closing issue 2
838 issue2.init_journal(User.find(:first), "Closing issue2")
854 issue2.init_journal(User.find(:first), "Closing issue2")
839 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
855 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
840 assert issue2.save
856 assert issue2.save
841 # 1 should not be also closed
857 # 1 should not be also closed
842 assert !issue1.reload.closed?
858 assert !issue1.reload.closed?
843 end
859 end
844
860
845 def test_assignable_versions
861 def test_assignable_versions
846 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
862 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
847 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
863 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
848 end
864 end
849
865
850 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
866 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
851 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
867 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
852 assert !issue.save
868 assert !issue.save
853 assert_not_nil issue.errors[:fixed_version_id]
869 assert_not_nil issue.errors[:fixed_version_id]
854 end
870 end
855
871
856 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
872 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
857 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
873 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
858 assert !issue.save
874 assert !issue.save
859 assert_not_nil issue.errors[:fixed_version_id]
875 assert_not_nil issue.errors[:fixed_version_id]
860 end
876 end
861
877
862 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
878 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
863 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
879 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
864 assert issue.save
880 assert issue.save
865 end
881 end
866
882
867 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
883 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
868 issue = Issue.find(11)
884 issue = Issue.find(11)
869 assert_equal 'closed', issue.fixed_version.status
885 assert_equal 'closed', issue.fixed_version.status
870 issue.subject = 'Subject changed'
886 issue.subject = 'Subject changed'
871 assert issue.save
887 assert issue.save
872 end
888 end
873
889
874 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
890 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
875 issue = Issue.find(11)
891 issue = Issue.find(11)
876 issue.status_id = 1
892 issue.status_id = 1
877 assert !issue.save
893 assert !issue.save
878 assert_not_nil issue.errors[:base]
894 assert_not_nil issue.errors[:base]
879 end
895 end
880
896
881 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
897 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
882 issue = Issue.find(11)
898 issue = Issue.find(11)
883 issue.status_id = 1
899 issue.status_id = 1
884 issue.fixed_version_id = 3
900 issue.fixed_version_id = 3
885 assert issue.save
901 assert issue.save
886 end
902 end
887
903
888 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
904 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
889 issue = Issue.find(12)
905 issue = Issue.find(12)
890 assert_equal 'locked', issue.fixed_version.status
906 assert_equal 'locked', issue.fixed_version.status
891 issue.status_id = 1
907 issue.status_id = 1
892 assert issue.save
908 assert issue.save
893 end
909 end
894
910
895 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
911 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
896 issue = Issue.find(2)
912 issue = Issue.find(2)
897 assert_equal 2, issue.fixed_version_id
913 assert_equal 2, issue.fixed_version_id
898 issue.project_id = 3
914 issue.project_id = 3
899 assert_nil issue.fixed_version_id
915 assert_nil issue.fixed_version_id
900 issue.fixed_version_id = 2
916 issue.fixed_version_id = 2
901 assert !issue.save
917 assert !issue.save
902 assert_include 'Target version is not included in the list', issue.errors.full_messages
918 assert_include 'Target version is not included in the list', issue.errors.full_messages
903 end
919 end
904
920
905 def test_should_keep_shared_version_when_changing_project
921 def test_should_keep_shared_version_when_changing_project
906 Version.find(2).update_attribute :sharing, 'tree'
922 Version.find(2).update_attribute :sharing, 'tree'
907
923
908 issue = Issue.find(2)
924 issue = Issue.find(2)
909 assert_equal 2, issue.fixed_version_id
925 assert_equal 2, issue.fixed_version_id
910 issue.project_id = 3
926 issue.project_id = 3
911 assert_equal 2, issue.fixed_version_id
927 assert_equal 2, issue.fixed_version_id
912 assert issue.save
928 assert issue.save
913 end
929 end
914
930
915 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
931 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
916 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
932 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
917 end
933 end
918
934
919 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
935 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
920 Project.find(2).disable_module! :issue_tracking
936 Project.find(2).disable_module! :issue_tracking
921 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
937 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
922 end
938 end
923
939
924 def test_move_to_another_project_with_same_category
940 def test_move_to_another_project_with_same_category
925 issue = Issue.find(1)
941 issue = Issue.find(1)
926 issue.project = Project.find(2)
942 issue.project = Project.find(2)
927 assert issue.save
943 assert issue.save
928 issue.reload
944 issue.reload
929 assert_equal 2, issue.project_id
945 assert_equal 2, issue.project_id
930 # Category changes
946 # Category changes
931 assert_equal 4, issue.category_id
947 assert_equal 4, issue.category_id
932 # Make sure time entries were move to the target project
948 # Make sure time entries were move to the target project
933 assert_equal 2, issue.time_entries.first.project_id
949 assert_equal 2, issue.time_entries.first.project_id
934 end
950 end
935
951
936 def test_move_to_another_project_without_same_category
952 def test_move_to_another_project_without_same_category
937 issue = Issue.find(2)
953 issue = Issue.find(2)
938 issue.project = Project.find(2)
954 issue.project = Project.find(2)
939 assert issue.save
955 assert issue.save
940 issue.reload
956 issue.reload
941 assert_equal 2, issue.project_id
957 assert_equal 2, issue.project_id
942 # Category cleared
958 # Category cleared
943 assert_nil issue.category_id
959 assert_nil issue.category_id
944 end
960 end
945
961
946 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
962 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
947 issue = Issue.find(1)
963 issue = Issue.find(1)
948 issue.update_attribute(:fixed_version_id, 1)
964 issue.update_attribute(:fixed_version_id, 1)
949 issue.project = Project.find(2)
965 issue.project = Project.find(2)
950 assert issue.save
966 assert issue.save
951 issue.reload
967 issue.reload
952 assert_equal 2, issue.project_id
968 assert_equal 2, issue.project_id
953 # Cleared fixed_version
969 # Cleared fixed_version
954 assert_equal nil, issue.fixed_version
970 assert_equal nil, issue.fixed_version
955 end
971 end
956
972
957 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
973 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
958 issue = Issue.find(1)
974 issue = Issue.find(1)
959 issue.update_attribute(:fixed_version_id, 4)
975 issue.update_attribute(:fixed_version_id, 4)
960 issue.project = Project.find(5)
976 issue.project = Project.find(5)
961 assert issue.save
977 assert issue.save
962 issue.reload
978 issue.reload
963 assert_equal 5, issue.project_id
979 assert_equal 5, issue.project_id
964 # Keep fixed_version
980 # Keep fixed_version
965 assert_equal 4, issue.fixed_version_id
981 assert_equal 4, issue.fixed_version_id
966 end
982 end
967
983
968 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
984 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
969 issue = Issue.find(1)
985 issue = Issue.find(1)
970 issue.update_attribute(:fixed_version_id, 1)
986 issue.update_attribute(:fixed_version_id, 1)
971 issue.project = Project.find(5)
987 issue.project = Project.find(5)
972 assert issue.save
988 assert issue.save
973 issue.reload
989 issue.reload
974 assert_equal 5, issue.project_id
990 assert_equal 5, issue.project_id
975 # Cleared fixed_version
991 # Cleared fixed_version
976 assert_equal nil, issue.fixed_version
992 assert_equal nil, issue.fixed_version
977 end
993 end
978
994
979 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
995 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
980 issue = Issue.find(1)
996 issue = Issue.find(1)
981 issue.update_attribute(:fixed_version_id, 7)
997 issue.update_attribute(:fixed_version_id, 7)
982 issue.project = Project.find(2)
998 issue.project = Project.find(2)
983 assert issue.save
999 assert issue.save
984 issue.reload
1000 issue.reload
985 assert_equal 2, issue.project_id
1001 assert_equal 2, issue.project_id
986 # Keep fixed_version
1002 # Keep fixed_version
987 assert_equal 7, issue.fixed_version_id
1003 assert_equal 7, issue.fixed_version_id
988 end
1004 end
989
1005
990 def test_move_to_another_project_should_keep_parent_if_valid
1006 def test_move_to_another_project_should_keep_parent_if_valid
991 issue = Issue.find(1)
1007 issue = Issue.find(1)
992 issue.update_attribute(:parent_issue_id, 2)
1008 issue.update_attribute(:parent_issue_id, 2)
993 issue.project = Project.find(3)
1009 issue.project = Project.find(3)
994 assert issue.save
1010 assert issue.save
995 issue.reload
1011 issue.reload
996 assert_equal 2, issue.parent_id
1012 assert_equal 2, issue.parent_id
997 end
1013 end
998
1014
999 def test_move_to_another_project_should_clear_parent_if_not_valid
1015 def test_move_to_another_project_should_clear_parent_if_not_valid
1000 issue = Issue.find(1)
1016 issue = Issue.find(1)
1001 issue.update_attribute(:parent_issue_id, 2)
1017 issue.update_attribute(:parent_issue_id, 2)
1002 issue.project = Project.find(2)
1018 issue.project = Project.find(2)
1003 assert issue.save
1019 assert issue.save
1004 issue.reload
1020 issue.reload
1005 assert_nil issue.parent_id
1021 assert_nil issue.parent_id
1006 end
1022 end
1007
1023
1008 def test_move_to_another_project_with_disabled_tracker
1024 def test_move_to_another_project_with_disabled_tracker
1009 issue = Issue.find(1)
1025 issue = Issue.find(1)
1010 target = Project.find(2)
1026 target = Project.find(2)
1011 target.tracker_ids = [3]
1027 target.tracker_ids = [3]
1012 target.save
1028 target.save
1013 issue.project = target
1029 issue.project = target
1014 assert issue.save
1030 assert issue.save
1015 issue.reload
1031 issue.reload
1016 assert_equal 2, issue.project_id
1032 assert_equal 2, issue.project_id
1017 assert_equal 3, issue.tracker_id
1033 assert_equal 3, issue.tracker_id
1018 end
1034 end
1019
1035
1020 def test_copy_to_the_same_project
1036 def test_copy_to_the_same_project
1021 issue = Issue.find(1)
1037 issue = Issue.find(1)
1022 copy = issue.copy
1038 copy = issue.copy
1023 assert_difference 'Issue.count' do
1039 assert_difference 'Issue.count' do
1024 copy.save!
1040 copy.save!
1025 end
1041 end
1026 assert_kind_of Issue, copy
1042 assert_kind_of Issue, copy
1027 assert_equal issue.project, copy.project
1043 assert_equal issue.project, copy.project
1028 assert_equal "125", copy.custom_value_for(2).value
1044 assert_equal "125", copy.custom_value_for(2).value
1029 end
1045 end
1030
1046
1031 def test_copy_to_another_project_and_tracker
1047 def test_copy_to_another_project_and_tracker
1032 issue = Issue.find(1)
1048 issue = Issue.find(1)
1033 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1049 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1034 assert_difference 'Issue.count' do
1050 assert_difference 'Issue.count' do
1035 copy.save!
1051 copy.save!
1036 end
1052 end
1037 copy.reload
1053 copy.reload
1038 assert_kind_of Issue, copy
1054 assert_kind_of Issue, copy
1039 assert_equal Project.find(3), copy.project
1055 assert_equal Project.find(3), copy.project
1040 assert_equal Tracker.find(2), copy.tracker
1056 assert_equal Tracker.find(2), copy.tracker
1041 # Custom field #2 is not associated with target tracker
1057 # Custom field #2 is not associated with target tracker
1042 assert_nil copy.custom_value_for(2)
1058 assert_nil copy.custom_value_for(2)
1043 end
1059 end
1044
1060
1045 context "#copy" do
1061 context "#copy" do
1046 setup do
1062 setup do
1047 @issue = Issue.find(1)
1063 @issue = Issue.find(1)
1048 end
1064 end
1049
1065
1050 should "not create a journal" do
1066 should "not create a journal" do
1051 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1067 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1052 copy.save!
1068 copy.save!
1053 assert_equal 0, copy.reload.journals.size
1069 assert_equal 0, copy.reload.journals.size
1054 end
1070 end
1055
1071
1056 should "allow assigned_to changes" do
1072 should "allow assigned_to changes" do
1057 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1073 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1058 assert_equal 3, copy.assigned_to_id
1074 assert_equal 3, copy.assigned_to_id
1059 end
1075 end
1060
1076
1061 should "allow status changes" do
1077 should "allow status changes" do
1062 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1078 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1063 assert_equal 2, copy.status_id
1079 assert_equal 2, copy.status_id
1064 end
1080 end
1065
1081
1066 should "allow start date changes" do
1082 should "allow start date changes" do
1067 date = Date.today
1083 date = Date.today
1068 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1084 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1069 assert_equal date, copy.start_date
1085 assert_equal date, copy.start_date
1070 end
1086 end
1071
1087
1072 should "allow due date changes" do
1088 should "allow due date changes" do
1073 date = Date.today
1089 date = Date.today
1074 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1090 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1075 assert_equal date, copy.due_date
1091 assert_equal date, copy.due_date
1076 end
1092 end
1077
1093
1078 should "set current user as author" do
1094 should "set current user as author" do
1079 User.current = User.find(9)
1095 User.current = User.find(9)
1080 copy = @issue.copy(:project_id => 3, :tracker_id => 2)
1096 copy = @issue.copy(:project_id => 3, :tracker_id => 2)
1081 assert_equal User.current, copy.author
1097 assert_equal User.current, copy.author
1082 end
1098 end
1083
1099
1084 should "create a journal with notes" do
1100 should "create a journal with notes" do
1085 date = Date.today
1101 date = Date.today
1086 notes = "Notes added when copying"
1102 notes = "Notes added when copying"
1087 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1103 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1088 copy.init_journal(User.current, notes)
1104 copy.init_journal(User.current, notes)
1089 copy.save!
1105 copy.save!
1090
1106
1091 assert_equal 1, copy.journals.size
1107 assert_equal 1, copy.journals.size
1092 journal = copy.journals.first
1108 journal = copy.journals.first
1093 assert_equal 0, journal.details.size
1109 assert_equal 0, journal.details.size
1094 assert_equal notes, journal.notes
1110 assert_equal notes, journal.notes
1095 end
1111 end
1096 end
1112 end
1097
1113
1098 def test_valid_parent_project
1114 def test_valid_parent_project
1099 issue = Issue.find(1)
1115 issue = Issue.find(1)
1100 issue_in_same_project = Issue.find(2)
1116 issue_in_same_project = Issue.find(2)
1101 issue_in_child_project = Issue.find(5)
1117 issue_in_child_project = Issue.find(5)
1102 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1118 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1103 issue_in_other_child_project = Issue.find(6)
1119 issue_in_other_child_project = Issue.find(6)
1104 issue_in_different_tree = Issue.find(4)
1120 issue_in_different_tree = Issue.find(4)
1105
1121
1106 with_settings :cross_project_subtasks => '' do
1122 with_settings :cross_project_subtasks => '' do
1107 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1123 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1108 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1124 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1109 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1125 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1110 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1126 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1111 end
1127 end
1112
1128
1113 with_settings :cross_project_subtasks => 'system' do
1129 with_settings :cross_project_subtasks => 'system' do
1114 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1130 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1115 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1131 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1116 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1132 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1117 end
1133 end
1118
1134
1119 with_settings :cross_project_subtasks => 'tree' do
1135 with_settings :cross_project_subtasks => 'tree' do
1120 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1136 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1121 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1137 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1122 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1138 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1123 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1139 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1124
1140
1125 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1141 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1126 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1142 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1127 end
1143 end
1128
1144
1129 with_settings :cross_project_subtasks => 'descendants' do
1145 with_settings :cross_project_subtasks => 'descendants' do
1130 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1146 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1131 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1147 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1132 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1148 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1133 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1149 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1134
1150
1135 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1151 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1136 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1152 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1137 end
1153 end
1138 end
1154 end
1139
1155
1140 def test_recipients_should_include_previous_assignee
1156 def test_recipients_should_include_previous_assignee
1141 user = User.find(3)
1157 user = User.find(3)
1142 user.members.update_all ["mail_notification = ?", false]
1158 user.members.update_all ["mail_notification = ?", false]
1143 user.update_attribute :mail_notification, 'only_assigned'
1159 user.update_attribute :mail_notification, 'only_assigned'
1144
1160
1145 issue = Issue.find(2)
1161 issue = Issue.find(2)
1146 issue.assigned_to = nil
1162 issue.assigned_to = nil
1147 assert_include user.mail, issue.recipients
1163 assert_include user.mail, issue.recipients
1148 issue.save!
1164 issue.save!
1149 assert !issue.recipients.include?(user.mail)
1165 assert !issue.recipients.include?(user.mail)
1150 end
1166 end
1151
1167
1152 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1168 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1153 issue = Issue.find(12)
1169 issue = Issue.find(12)
1154 assert issue.recipients.include?(issue.author.mail)
1170 assert issue.recipients.include?(issue.author.mail)
1155 # copy the issue to a private project
1171 # copy the issue to a private project
1156 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1172 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1157 # author is not a member of project anymore
1173 # author is not a member of project anymore
1158 assert !copy.recipients.include?(copy.author.mail)
1174 assert !copy.recipients.include?(copy.author.mail)
1159 end
1175 end
1160
1176
1161 def test_recipients_should_include_the_assigned_group_members
1177 def test_recipients_should_include_the_assigned_group_members
1162 group_member = User.generate!
1178 group_member = User.generate!
1163 group = Group.generate!
1179 group = Group.generate!
1164 group.users << group_member
1180 group.users << group_member
1165
1181
1166 issue = Issue.find(12)
1182 issue = Issue.find(12)
1167 issue.assigned_to = group
1183 issue.assigned_to = group
1168 assert issue.recipients.include?(group_member.mail)
1184 assert issue.recipients.include?(group_member.mail)
1169 end
1185 end
1170
1186
1171 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1187 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1172 user = User.find(3)
1188 user = User.find(3)
1173 issue = Issue.find(9)
1189 issue = Issue.find(9)
1174 Watcher.create!(:user => user, :watchable => issue)
1190 Watcher.create!(:user => user, :watchable => issue)
1175 assert issue.watched_by?(user)
1191 assert issue.watched_by?(user)
1176 assert !issue.watcher_recipients.include?(user.mail)
1192 assert !issue.watcher_recipients.include?(user.mail)
1177 end
1193 end
1178
1194
1179 def test_issue_destroy
1195 def test_issue_destroy
1180 Issue.find(1).destroy
1196 Issue.find(1).destroy
1181 assert_nil Issue.find_by_id(1)
1197 assert_nil Issue.find_by_id(1)
1182 assert_nil TimeEntry.find_by_issue_id(1)
1198 assert_nil TimeEntry.find_by_issue_id(1)
1183 end
1199 end
1184
1200
1185 def test_destroying_a_deleted_issue_should_not_raise_an_error
1201 def test_destroying_a_deleted_issue_should_not_raise_an_error
1186 issue = Issue.find(1)
1202 issue = Issue.find(1)
1187 Issue.find(1).destroy
1203 Issue.find(1).destroy
1188
1204
1189 assert_nothing_raised do
1205 assert_nothing_raised do
1190 assert_no_difference 'Issue.count' do
1206 assert_no_difference 'Issue.count' do
1191 issue.destroy
1207 issue.destroy
1192 end
1208 end
1193 assert issue.destroyed?
1209 assert issue.destroyed?
1194 end
1210 end
1195 end
1211 end
1196
1212
1197 def test_destroying_a_stale_issue_should_not_raise_an_error
1213 def test_destroying_a_stale_issue_should_not_raise_an_error
1198 issue = Issue.find(1)
1214 issue = Issue.find(1)
1199 Issue.find(1).update_attribute :subject, "Updated"
1215 Issue.find(1).update_attribute :subject, "Updated"
1200
1216
1201 assert_nothing_raised do
1217 assert_nothing_raised do
1202 assert_difference 'Issue.count', -1 do
1218 assert_difference 'Issue.count', -1 do
1203 issue.destroy
1219 issue.destroy
1204 end
1220 end
1205 assert issue.destroyed?
1221 assert issue.destroyed?
1206 end
1222 end
1207 end
1223 end
1208
1224
1209 def test_blocked
1225 def test_blocked
1210 blocked_issue = Issue.find(9)
1226 blocked_issue = Issue.find(9)
1211 blocking_issue = Issue.find(10)
1227 blocking_issue = Issue.find(10)
1212
1228
1213 assert blocked_issue.blocked?
1229 assert blocked_issue.blocked?
1214 assert !blocking_issue.blocked?
1230 assert !blocking_issue.blocked?
1215 end
1231 end
1216
1232
1217 def test_blocked_issues_dont_allow_closed_statuses
1233 def test_blocked_issues_dont_allow_closed_statuses
1218 blocked_issue = Issue.find(9)
1234 blocked_issue = Issue.find(9)
1219
1235
1220 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1236 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1221 assert !allowed_statuses.empty?
1237 assert !allowed_statuses.empty?
1222 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1238 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1223 assert closed_statuses.empty?
1239 assert closed_statuses.empty?
1224 end
1240 end
1225
1241
1226 def test_unblocked_issues_allow_closed_statuses
1242 def test_unblocked_issues_allow_closed_statuses
1227 blocking_issue = Issue.find(10)
1243 blocking_issue = Issue.find(10)
1228
1244
1229 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1245 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1230 assert !allowed_statuses.empty?
1246 assert !allowed_statuses.empty?
1231 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1247 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1232 assert !closed_statuses.empty?
1248 assert !closed_statuses.empty?
1233 end
1249 end
1234
1250
1235 def test_rescheduling_an_issue_should_reschedule_following_issue
1251 def test_rescheduling_an_issue_should_reschedule_following_issue
1236 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1,
1252 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1,
1237 :author_id => 1, :status_id => 1,
1253 :author_id => 1, :status_id => 1,
1238 :subject => '-',
1254 :subject => '-',
1239 :start_date => Date.today, :due_date => Date.today + 2)
1255 :start_date => Date.today, :due_date => Date.today + 2)
1240 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1,
1256 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1,
1241 :author_id => 1, :status_id => 1,
1257 :author_id => 1, :status_id => 1,
1242 :subject => '-',
1258 :subject => '-',
1243 :start_date => Date.today, :due_date => Date.today + 2)
1259 :start_date => Date.today, :due_date => Date.today + 2)
1244 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1260 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1245 :relation_type => IssueRelation::TYPE_PRECEDES)
1261 :relation_type => IssueRelation::TYPE_PRECEDES)
1246 assert_equal issue1.due_date + 1, issue2.reload.start_date
1262 assert_equal issue1.due_date + 1, issue2.reload.start_date
1247
1263
1248 issue1.due_date = Date.today + 5
1264 issue1.due_date = Date.today + 5
1249 issue1.save!
1265 issue1.save!
1250 assert_equal issue1.due_date + 1, issue2.reload.start_date
1266 assert_equal issue1.due_date + 1, issue2.reload.start_date
1251 end
1267 end
1252
1268
1253 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1269 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1254 stale = Issue.find(1)
1270 stale = Issue.find(1)
1255 issue = Issue.find(1)
1271 issue = Issue.find(1)
1256 issue.subject = "Updated"
1272 issue.subject = "Updated"
1257 issue.save!
1273 issue.save!
1258
1274
1259 date = 10.days.from_now.to_date
1275 date = 10.days.from_now.to_date
1260 assert_nothing_raised do
1276 assert_nothing_raised do
1261 stale.reschedule_after(date)
1277 stale.reschedule_after(date)
1262 end
1278 end
1263 assert_equal date, stale.reload.start_date
1279 assert_equal date, stale.reload.start_date
1264 end
1280 end
1265
1281
1266 def test_overdue
1282 def test_overdue
1267 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1283 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1268 assert !Issue.new(:due_date => Date.today).overdue?
1284 assert !Issue.new(:due_date => Date.today).overdue?
1269 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1285 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1270 assert !Issue.new(:due_date => nil).overdue?
1286 assert !Issue.new(:due_date => nil).overdue?
1271 assert !Issue.new(:due_date => 1.day.ago.to_date,
1287 assert !Issue.new(:due_date => 1.day.ago.to_date,
1272 :status => IssueStatus.find(:first,
1288 :status => IssueStatus.find(:first,
1273 :conditions => {:is_closed => true})
1289 :conditions => {:is_closed => true})
1274 ).overdue?
1290 ).overdue?
1275 end
1291 end
1276
1292
1277 context "#behind_schedule?" do
1293 context "#behind_schedule?" do
1278 should "be false if the issue has no start_date" do
1294 should "be false if the issue has no start_date" do
1279 assert !Issue.new(:start_date => nil,
1295 assert !Issue.new(:start_date => nil,
1280 :due_date => 1.day.from_now.to_date,
1296 :due_date => 1.day.from_now.to_date,
1281 :done_ratio => 0).behind_schedule?
1297 :done_ratio => 0).behind_schedule?
1282 end
1298 end
1283
1299
1284 should "be false if the issue has no end_date" do
1300 should "be false if the issue has no end_date" do
1285 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1301 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1286 :due_date => nil,
1302 :due_date => nil,
1287 :done_ratio => 0).behind_schedule?
1303 :done_ratio => 0).behind_schedule?
1288 end
1304 end
1289
1305
1290 should "be false if the issue has more done than it's calendar time" do
1306 should "be false if the issue has more done than it's calendar time" do
1291 assert !Issue.new(:start_date => 50.days.ago.to_date,
1307 assert !Issue.new(:start_date => 50.days.ago.to_date,
1292 :due_date => 50.days.from_now.to_date,
1308 :due_date => 50.days.from_now.to_date,
1293 :done_ratio => 90).behind_schedule?
1309 :done_ratio => 90).behind_schedule?
1294 end
1310 end
1295
1311
1296 should "be true if the issue hasn't been started at all" do
1312 should "be true if the issue hasn't been started at all" do
1297 assert Issue.new(:start_date => 1.day.ago.to_date,
1313 assert Issue.new(:start_date => 1.day.ago.to_date,
1298 :due_date => 1.day.from_now.to_date,
1314 :due_date => 1.day.from_now.to_date,
1299 :done_ratio => 0).behind_schedule?
1315 :done_ratio => 0).behind_schedule?
1300 end
1316 end
1301
1317
1302 should "be true if the issue has used more calendar time than it's done ratio" do
1318 should "be true if the issue has used more calendar time than it's done ratio" do
1303 assert Issue.new(:start_date => 100.days.ago.to_date,
1319 assert Issue.new(:start_date => 100.days.ago.to_date,
1304 :due_date => Date.today,
1320 :due_date => Date.today,
1305 :done_ratio => 90).behind_schedule?
1321 :done_ratio => 90).behind_schedule?
1306 end
1322 end
1307 end
1323 end
1308
1324
1309 context "#assignable_users" do
1325 context "#assignable_users" do
1310 should "be Users" do
1326 should "be Users" do
1311 assert_kind_of User, Issue.find(1).assignable_users.first
1327 assert_kind_of User, Issue.find(1).assignable_users.first
1312 end
1328 end
1313
1329
1314 should "include the issue author" do
1330 should "include the issue author" do
1315 non_project_member = User.generate!
1331 non_project_member = User.generate!
1316 issue = Issue.generate!(:author => non_project_member)
1332 issue = Issue.generate!(:author => non_project_member)
1317
1333
1318 assert issue.assignable_users.include?(non_project_member)
1334 assert issue.assignable_users.include?(non_project_member)
1319 end
1335 end
1320
1336
1321 should "include the current assignee" do
1337 should "include the current assignee" do
1322 user = User.generate!
1338 user = User.generate!
1323 issue = Issue.generate!(:assigned_to => user)
1339 issue = Issue.generate!(:assigned_to => user)
1324 user.lock!
1340 user.lock!
1325
1341
1326 assert Issue.find(issue.id).assignable_users.include?(user)
1342 assert Issue.find(issue.id).assignable_users.include?(user)
1327 end
1343 end
1328
1344
1329 should "not show the issue author twice" do
1345 should "not show the issue author twice" do
1330 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1346 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1331 assert_equal 2, assignable_user_ids.length
1347 assert_equal 2, assignable_user_ids.length
1332
1348
1333 assignable_user_ids.each do |user_id|
1349 assignable_user_ids.each do |user_id|
1334 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1350 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1335 "User #{user_id} appears more or less than once"
1351 "User #{user_id} appears more or less than once"
1336 end
1352 end
1337 end
1353 end
1338
1354
1339 context "with issue_group_assignment" do
1355 context "with issue_group_assignment" do
1340 should "include groups" do
1356 should "include groups" do
1341 issue = Issue.new(:project => Project.find(2))
1357 issue = Issue.new(:project => Project.find(2))
1342
1358
1343 with_settings :issue_group_assignment => '1' do
1359 with_settings :issue_group_assignment => '1' do
1344 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1360 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1345 assert issue.assignable_users.include?(Group.find(11))
1361 assert issue.assignable_users.include?(Group.find(11))
1346 end
1362 end
1347 end
1363 end
1348 end
1364 end
1349
1365
1350 context "without issue_group_assignment" do
1366 context "without issue_group_assignment" do
1351 should "not include groups" do
1367 should "not include groups" do
1352 issue = Issue.new(:project => Project.find(2))
1368 issue = Issue.new(:project => Project.find(2))
1353
1369
1354 with_settings :issue_group_assignment => '0' do
1370 with_settings :issue_group_assignment => '0' do
1355 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1371 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1356 assert !issue.assignable_users.include?(Group.find(11))
1372 assert !issue.assignable_users.include?(Group.find(11))
1357 end
1373 end
1358 end
1374 end
1359 end
1375 end
1360 end
1376 end
1361
1377
1362 def test_create_should_send_email_notification
1378 def test_create_should_send_email_notification
1363 ActionMailer::Base.deliveries.clear
1379 ActionMailer::Base.deliveries.clear
1364 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1380 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1365 :author_id => 3, :status_id => 1,
1381 :author_id => 3, :status_id => 1,
1366 :priority => IssuePriority.all.first,
1382 :priority => IssuePriority.all.first,
1367 :subject => 'test_create', :estimated_hours => '1:30')
1383 :subject => 'test_create', :estimated_hours => '1:30')
1368
1384
1369 assert issue.save
1385 assert issue.save
1370 assert_equal 1, ActionMailer::Base.deliveries.size
1386 assert_equal 1, ActionMailer::Base.deliveries.size
1371 end
1387 end
1372
1388
1373 def test_stale_issue_should_not_send_email_notification
1389 def test_stale_issue_should_not_send_email_notification
1374 ActionMailer::Base.deliveries.clear
1390 ActionMailer::Base.deliveries.clear
1375 issue = Issue.find(1)
1391 issue = Issue.find(1)
1376 stale = Issue.find(1)
1392 stale = Issue.find(1)
1377
1393
1378 issue.init_journal(User.find(1))
1394 issue.init_journal(User.find(1))
1379 issue.subject = 'Subjet update'
1395 issue.subject = 'Subjet update'
1380 assert issue.save
1396 assert issue.save
1381 assert_equal 1, ActionMailer::Base.deliveries.size
1397 assert_equal 1, ActionMailer::Base.deliveries.size
1382 ActionMailer::Base.deliveries.clear
1398 ActionMailer::Base.deliveries.clear
1383
1399
1384 stale.init_journal(User.find(1))
1400 stale.init_journal(User.find(1))
1385 stale.subject = 'Another subjet update'
1401 stale.subject = 'Another subjet update'
1386 assert_raise ActiveRecord::StaleObjectError do
1402 assert_raise ActiveRecord::StaleObjectError do
1387 stale.save
1403 stale.save
1388 end
1404 end
1389 assert ActionMailer::Base.deliveries.empty?
1405 assert ActionMailer::Base.deliveries.empty?
1390 end
1406 end
1391
1407
1392 def test_journalized_description
1408 def test_journalized_description
1393 IssueCustomField.delete_all
1409 IssueCustomField.delete_all
1394
1410
1395 i = Issue.first
1411 i = Issue.first
1396 old_description = i.description
1412 old_description = i.description
1397 new_description = "This is the new description"
1413 new_description = "This is the new description"
1398
1414
1399 i.init_journal(User.find(2))
1415 i.init_journal(User.find(2))
1400 i.description = new_description
1416 i.description = new_description
1401 assert_difference 'Journal.count', 1 do
1417 assert_difference 'Journal.count', 1 do
1402 assert_difference 'JournalDetail.count', 1 do
1418 assert_difference 'JournalDetail.count', 1 do
1403 i.save!
1419 i.save!
1404 end
1420 end
1405 end
1421 end
1406
1422
1407 detail = JournalDetail.first(:order => 'id DESC')
1423 detail = JournalDetail.first(:order => 'id DESC')
1408 assert_equal i, detail.journal.journalized
1424 assert_equal i, detail.journal.journalized
1409 assert_equal 'attr', detail.property
1425 assert_equal 'attr', detail.property
1410 assert_equal 'description', detail.prop_key
1426 assert_equal 'description', detail.prop_key
1411 assert_equal old_description, detail.old_value
1427 assert_equal old_description, detail.old_value
1412 assert_equal new_description, detail.value
1428 assert_equal new_description, detail.value
1413 end
1429 end
1414
1430
1415 def test_blank_descriptions_should_not_be_journalized
1431 def test_blank_descriptions_should_not_be_journalized
1416 IssueCustomField.delete_all
1432 IssueCustomField.delete_all
1417 Issue.update_all("description = NULL", "id=1")
1433 Issue.update_all("description = NULL", "id=1")
1418
1434
1419 i = Issue.find(1)
1435 i = Issue.find(1)
1420 i.init_journal(User.find(2))
1436 i.init_journal(User.find(2))
1421 i.subject = "blank description"
1437 i.subject = "blank description"
1422 i.description = "\r\n"
1438 i.description = "\r\n"
1423
1439
1424 assert_difference 'Journal.count', 1 do
1440 assert_difference 'Journal.count', 1 do
1425 assert_difference 'JournalDetail.count', 1 do
1441 assert_difference 'JournalDetail.count', 1 do
1426 i.save!
1442 i.save!
1427 end
1443 end
1428 end
1444 end
1429 end
1445 end
1430
1446
1431 def test_journalized_multi_custom_field
1447 def test_journalized_multi_custom_field
1432 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1448 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1433 :is_filter => true, :is_for_all => true,
1449 :is_filter => true, :is_for_all => true,
1434 :tracker_ids => [1],
1450 :tracker_ids => [1],
1435 :possible_values => ['value1', 'value2', 'value3'],
1451 :possible_values => ['value1', 'value2', 'value3'],
1436 :multiple => true)
1452 :multiple => true)
1437
1453
1438 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1454 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1439 :subject => 'Test', :author_id => 1)
1455 :subject => 'Test', :author_id => 1)
1440
1456
1441 assert_difference 'Journal.count' do
1457 assert_difference 'Journal.count' do
1442 assert_difference 'JournalDetail.count' do
1458 assert_difference 'JournalDetail.count' do
1443 issue.init_journal(User.first)
1459 issue.init_journal(User.first)
1444 issue.custom_field_values = {field.id => ['value1']}
1460 issue.custom_field_values = {field.id => ['value1']}
1445 issue.save!
1461 issue.save!
1446 end
1462 end
1447 assert_difference 'JournalDetail.count' do
1463 assert_difference 'JournalDetail.count' do
1448 issue.init_journal(User.first)
1464 issue.init_journal(User.first)
1449 issue.custom_field_values = {field.id => ['value1', 'value2']}
1465 issue.custom_field_values = {field.id => ['value1', 'value2']}
1450 issue.save!
1466 issue.save!
1451 end
1467 end
1452 assert_difference 'JournalDetail.count', 2 do
1468 assert_difference 'JournalDetail.count', 2 do
1453 issue.init_journal(User.first)
1469 issue.init_journal(User.first)
1454 issue.custom_field_values = {field.id => ['value3', 'value2']}
1470 issue.custom_field_values = {field.id => ['value3', 'value2']}
1455 issue.save!
1471 issue.save!
1456 end
1472 end
1457 assert_difference 'JournalDetail.count', 2 do
1473 assert_difference 'JournalDetail.count', 2 do
1458 issue.init_journal(User.first)
1474 issue.init_journal(User.first)
1459 issue.custom_field_values = {field.id => nil}
1475 issue.custom_field_values = {field.id => nil}
1460 issue.save!
1476 issue.save!
1461 end
1477 end
1462 end
1478 end
1463 end
1479 end
1464
1480
1465 def test_description_eol_should_be_normalized
1481 def test_description_eol_should_be_normalized
1466 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1482 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1467 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1483 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1468 end
1484 end
1469
1485
1470 def test_saving_twice_should_not_duplicate_journal_details
1486 def test_saving_twice_should_not_duplicate_journal_details
1471 i = Issue.find(:first)
1487 i = Issue.find(:first)
1472 i.init_journal(User.find(2), 'Some notes')
1488 i.init_journal(User.find(2), 'Some notes')
1473 # initial changes
1489 # initial changes
1474 i.subject = 'New subject'
1490 i.subject = 'New subject'
1475 i.done_ratio = i.done_ratio + 10
1491 i.done_ratio = i.done_ratio + 10
1476 assert_difference 'Journal.count' do
1492 assert_difference 'Journal.count' do
1477 assert i.save
1493 assert i.save
1478 end
1494 end
1479 # 1 more change
1495 # 1 more change
1480 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
1496 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
1481 assert_no_difference 'Journal.count' do
1497 assert_no_difference 'Journal.count' do
1482 assert_difference 'JournalDetail.count', 1 do
1498 assert_difference 'JournalDetail.count', 1 do
1483 i.save
1499 i.save
1484 end
1500 end
1485 end
1501 end
1486 # no more change
1502 # no more change
1487 assert_no_difference 'Journal.count' do
1503 assert_no_difference 'Journal.count' do
1488 assert_no_difference 'JournalDetail.count' do
1504 assert_no_difference 'JournalDetail.count' do
1489 i.save
1505 i.save
1490 end
1506 end
1491 end
1507 end
1492 end
1508 end
1493
1509
1494 def test_all_dependent_issues
1510 def test_all_dependent_issues
1495 IssueRelation.delete_all
1511 IssueRelation.delete_all
1496 assert IssueRelation.create!(:issue_from => Issue.find(1),
1512 assert IssueRelation.create!(:issue_from => Issue.find(1),
1497 :issue_to => Issue.find(2),
1513 :issue_to => Issue.find(2),
1498 :relation_type => IssueRelation::TYPE_PRECEDES)
1514 :relation_type => IssueRelation::TYPE_PRECEDES)
1499 assert IssueRelation.create!(:issue_from => Issue.find(2),
1515 assert IssueRelation.create!(:issue_from => Issue.find(2),
1500 :issue_to => Issue.find(3),
1516 :issue_to => Issue.find(3),
1501 :relation_type => IssueRelation::TYPE_PRECEDES)
1517 :relation_type => IssueRelation::TYPE_PRECEDES)
1502 assert IssueRelation.create!(:issue_from => Issue.find(3),
1518 assert IssueRelation.create!(:issue_from => Issue.find(3),
1503 :issue_to => Issue.find(8),
1519 :issue_to => Issue.find(8),
1504 :relation_type => IssueRelation::TYPE_PRECEDES)
1520 :relation_type => IssueRelation::TYPE_PRECEDES)
1505
1521
1506 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1522 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1507 end
1523 end
1508
1524
1509 def test_all_dependent_issues_with_persistent_circular_dependency
1525 def test_all_dependent_issues_with_persistent_circular_dependency
1510 IssueRelation.delete_all
1526 IssueRelation.delete_all
1511 assert IssueRelation.create!(:issue_from => Issue.find(1),
1527 assert IssueRelation.create!(:issue_from => Issue.find(1),
1512 :issue_to => Issue.find(2),
1528 :issue_to => Issue.find(2),
1513 :relation_type => IssueRelation::TYPE_PRECEDES)
1529 :relation_type => IssueRelation::TYPE_PRECEDES)
1514 assert IssueRelation.create!(:issue_from => Issue.find(2),
1530 assert IssueRelation.create!(:issue_from => Issue.find(2),
1515 :issue_to => Issue.find(3),
1531 :issue_to => Issue.find(3),
1516 :relation_type => IssueRelation::TYPE_PRECEDES)
1532 :relation_type => IssueRelation::TYPE_PRECEDES)
1517
1533
1518 r = IssueRelation.create!(:issue_from => Issue.find(3),
1534 r = IssueRelation.create!(:issue_from => Issue.find(3),
1519 :issue_to => Issue.find(7),
1535 :issue_to => Issue.find(7),
1520 :relation_type => IssueRelation::TYPE_PRECEDES)
1536 :relation_type => IssueRelation::TYPE_PRECEDES)
1521 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1537 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1522
1538
1523 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1539 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1524 end
1540 end
1525
1541
1526 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1542 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1527 IssueRelation.delete_all
1543 IssueRelation.delete_all
1528 assert IssueRelation.create!(:issue_from => Issue.find(1),
1544 assert IssueRelation.create!(:issue_from => Issue.find(1),
1529 :issue_to => Issue.find(2),
1545 :issue_to => Issue.find(2),
1530 :relation_type => IssueRelation::TYPE_RELATES)
1546 :relation_type => IssueRelation::TYPE_RELATES)
1531 assert IssueRelation.create!(:issue_from => Issue.find(2),
1547 assert IssueRelation.create!(:issue_from => Issue.find(2),
1532 :issue_to => Issue.find(3),
1548 :issue_to => Issue.find(3),
1533 :relation_type => IssueRelation::TYPE_RELATES)
1549 :relation_type => IssueRelation::TYPE_RELATES)
1534 assert IssueRelation.create!(:issue_from => Issue.find(3),
1550 assert IssueRelation.create!(:issue_from => Issue.find(3),
1535 :issue_to => Issue.find(8),
1551 :issue_to => Issue.find(8),
1536 :relation_type => IssueRelation::TYPE_RELATES)
1552 :relation_type => IssueRelation::TYPE_RELATES)
1537
1553
1538 r = IssueRelation.create!(:issue_from => Issue.find(8),
1554 r = IssueRelation.create!(:issue_from => Issue.find(8),
1539 :issue_to => Issue.find(7),
1555 :issue_to => Issue.find(7),
1540 :relation_type => IssueRelation::TYPE_RELATES)
1556 :relation_type => IssueRelation::TYPE_RELATES)
1541 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1557 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1542
1558
1543 r = IssueRelation.create!(:issue_from => Issue.find(3),
1559 r = IssueRelation.create!(:issue_from => Issue.find(3),
1544 :issue_to => Issue.find(7),
1560 :issue_to => Issue.find(7),
1545 :relation_type => IssueRelation::TYPE_RELATES)
1561 :relation_type => IssueRelation::TYPE_RELATES)
1546 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1562 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1547
1563
1548 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1564 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1549 end
1565 end
1550
1566
1551 context "#done_ratio" do
1567 context "#done_ratio" do
1552 setup do
1568 setup do
1553 @issue = Issue.find(1)
1569 @issue = Issue.find(1)
1554 @issue_status = IssueStatus.find(1)
1570 @issue_status = IssueStatus.find(1)
1555 @issue_status.update_attribute(:default_done_ratio, 50)
1571 @issue_status.update_attribute(:default_done_ratio, 50)
1556 @issue2 = Issue.find(2)
1572 @issue2 = Issue.find(2)
1557 @issue_status2 = IssueStatus.find(2)
1573 @issue_status2 = IssueStatus.find(2)
1558 @issue_status2.update_attribute(:default_done_ratio, 0)
1574 @issue_status2.update_attribute(:default_done_ratio, 0)
1559 end
1575 end
1560
1576
1561 teardown do
1577 teardown do
1562 Setting.issue_done_ratio = 'issue_field'
1578 Setting.issue_done_ratio = 'issue_field'
1563 end
1579 end
1564
1580
1565 context "with Setting.issue_done_ratio using the issue_field" do
1581 context "with Setting.issue_done_ratio using the issue_field" do
1566 setup do
1582 setup do
1567 Setting.issue_done_ratio = 'issue_field'
1583 Setting.issue_done_ratio = 'issue_field'
1568 end
1584 end
1569
1585
1570 should "read the issue's field" do
1586 should "read the issue's field" do
1571 assert_equal 0, @issue.done_ratio
1587 assert_equal 0, @issue.done_ratio
1572 assert_equal 30, @issue2.done_ratio
1588 assert_equal 30, @issue2.done_ratio
1573 end
1589 end
1574 end
1590 end
1575
1591
1576 context "with Setting.issue_done_ratio using the issue_status" do
1592 context "with Setting.issue_done_ratio using the issue_status" do
1577 setup do
1593 setup do
1578 Setting.issue_done_ratio = 'issue_status'
1594 Setting.issue_done_ratio = 'issue_status'
1579 end
1595 end
1580
1596
1581 should "read the Issue Status's default done ratio" do
1597 should "read the Issue Status's default done ratio" do
1582 assert_equal 50, @issue.done_ratio
1598 assert_equal 50, @issue.done_ratio
1583 assert_equal 0, @issue2.done_ratio
1599 assert_equal 0, @issue2.done_ratio
1584 end
1600 end
1585 end
1601 end
1586 end
1602 end
1587
1603
1588 context "#update_done_ratio_from_issue_status" do
1604 context "#update_done_ratio_from_issue_status" do
1589 setup do
1605 setup do
1590 @issue = Issue.find(1)
1606 @issue = Issue.find(1)
1591 @issue_status = IssueStatus.find(1)
1607 @issue_status = IssueStatus.find(1)
1592 @issue_status.update_attribute(:default_done_ratio, 50)
1608 @issue_status.update_attribute(:default_done_ratio, 50)
1593 @issue2 = Issue.find(2)
1609 @issue2 = Issue.find(2)
1594 @issue_status2 = IssueStatus.find(2)
1610 @issue_status2 = IssueStatus.find(2)
1595 @issue_status2.update_attribute(:default_done_ratio, 0)
1611 @issue_status2.update_attribute(:default_done_ratio, 0)
1596 end
1612 end
1597
1613
1598 context "with Setting.issue_done_ratio using the issue_field" do
1614 context "with Setting.issue_done_ratio using the issue_field" do
1599 setup do
1615 setup do
1600 Setting.issue_done_ratio = 'issue_field'
1616 Setting.issue_done_ratio = 'issue_field'
1601 end
1617 end
1602
1618
1603 should "not change the issue" do
1619 should "not change the issue" do
1604 @issue.update_done_ratio_from_issue_status
1620 @issue.update_done_ratio_from_issue_status
1605 @issue2.update_done_ratio_from_issue_status
1621 @issue2.update_done_ratio_from_issue_status
1606
1622
1607 assert_equal 0, @issue.read_attribute(:done_ratio)
1623 assert_equal 0, @issue.read_attribute(:done_ratio)
1608 assert_equal 30, @issue2.read_attribute(:done_ratio)
1624 assert_equal 30, @issue2.read_attribute(:done_ratio)
1609 end
1625 end
1610 end
1626 end
1611
1627
1612 context "with Setting.issue_done_ratio using the issue_status" do
1628 context "with Setting.issue_done_ratio using the issue_status" do
1613 setup do
1629 setup do
1614 Setting.issue_done_ratio = 'issue_status'
1630 Setting.issue_done_ratio = 'issue_status'
1615 end
1631 end
1616
1632
1617 should "change the issue's done ratio" do
1633 should "change the issue's done ratio" do
1618 @issue.update_done_ratio_from_issue_status
1634 @issue.update_done_ratio_from_issue_status
1619 @issue2.update_done_ratio_from_issue_status
1635 @issue2.update_done_ratio_from_issue_status
1620
1636
1621 assert_equal 50, @issue.read_attribute(:done_ratio)
1637 assert_equal 50, @issue.read_attribute(:done_ratio)
1622 assert_equal 0, @issue2.read_attribute(:done_ratio)
1638 assert_equal 0, @issue2.read_attribute(:done_ratio)
1623 end
1639 end
1624 end
1640 end
1625 end
1641 end
1626
1642
1627 test "#by_tracker" do
1643 test "#by_tracker" do
1628 User.current = User.anonymous
1644 User.current = User.anonymous
1629 groups = Issue.by_tracker(Project.find(1))
1645 groups = Issue.by_tracker(Project.find(1))
1630 assert_equal 3, groups.size
1646 assert_equal 3, groups.size
1631 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1647 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1632 end
1648 end
1633
1649
1634 test "#by_version" do
1650 test "#by_version" do
1635 User.current = User.anonymous
1651 User.current = User.anonymous
1636 groups = Issue.by_version(Project.find(1))
1652 groups = Issue.by_version(Project.find(1))
1637 assert_equal 3, groups.size
1653 assert_equal 3, groups.size
1638 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1654 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1639 end
1655 end
1640
1656
1641 test "#by_priority" do
1657 test "#by_priority" do
1642 User.current = User.anonymous
1658 User.current = User.anonymous
1643 groups = Issue.by_priority(Project.find(1))
1659 groups = Issue.by_priority(Project.find(1))
1644 assert_equal 4, groups.size
1660 assert_equal 4, groups.size
1645 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1661 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1646 end
1662 end
1647
1663
1648 test "#by_category" do
1664 test "#by_category" do
1649 User.current = User.anonymous
1665 User.current = User.anonymous
1650 groups = Issue.by_category(Project.find(1))
1666 groups = Issue.by_category(Project.find(1))
1651 assert_equal 2, groups.size
1667 assert_equal 2, groups.size
1652 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1668 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1653 end
1669 end
1654
1670
1655 test "#by_assigned_to" do
1671 test "#by_assigned_to" do
1656 User.current = User.anonymous
1672 User.current = User.anonymous
1657 groups = Issue.by_assigned_to(Project.find(1))
1673 groups = Issue.by_assigned_to(Project.find(1))
1658 assert_equal 2, groups.size
1674 assert_equal 2, groups.size
1659 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1675 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1660 end
1676 end
1661
1677
1662 test "#by_author" do
1678 test "#by_author" do
1663 User.current = User.anonymous
1679 User.current = User.anonymous
1664 groups = Issue.by_author(Project.find(1))
1680 groups = Issue.by_author(Project.find(1))
1665 assert_equal 4, groups.size
1681 assert_equal 4, groups.size
1666 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1682 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1667 end
1683 end
1668
1684
1669 test "#by_subproject" do
1685 test "#by_subproject" do
1670 User.current = User.anonymous
1686 User.current = User.anonymous
1671 groups = Issue.by_subproject(Project.find(1))
1687 groups = Issue.by_subproject(Project.find(1))
1672 # Private descendant not visible
1688 # Private descendant not visible
1673 assert_equal 1, groups.size
1689 assert_equal 1, groups.size
1674 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1690 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1675 end
1691 end
1676
1692
1677 def test_recently_updated_scope
1693 def test_recently_updated_scope
1678 #should return the last updated issue
1694 #should return the last updated issue
1679 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1695 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1680 end
1696 end
1681
1697
1682 def test_on_active_projects_scope
1698 def test_on_active_projects_scope
1683 assert Project.find(2).archive
1699 assert Project.find(2).archive
1684
1700
1685 before = Issue.on_active_project.length
1701 before = Issue.on_active_project.length
1686 # test inclusion to results
1702 # test inclusion to results
1687 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1703 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1688 assert_equal before + 1, Issue.on_active_project.length
1704 assert_equal before + 1, Issue.on_active_project.length
1689
1705
1690 # Move to an archived project
1706 # Move to an archived project
1691 issue.project = Project.find(2)
1707 issue.project = Project.find(2)
1692 assert issue.save
1708 assert issue.save
1693 assert_equal before, Issue.on_active_project.length
1709 assert_equal before, Issue.on_active_project.length
1694 end
1710 end
1695
1711
1696 context "Issue#recipients" do
1712 context "Issue#recipients" do
1697 setup do
1713 setup do
1698 @project = Project.find(1)
1714 @project = Project.find(1)
1699 @author = User.generate!
1715 @author = User.generate!
1700 @assignee = User.generate!
1716 @assignee = User.generate!
1701 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1717 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1702 end
1718 end
1703
1719
1704 should "include project recipients" do
1720 should "include project recipients" do
1705 assert @project.recipients.present?
1721 assert @project.recipients.present?
1706 @project.recipients.each do |project_recipient|
1722 @project.recipients.each do |project_recipient|
1707 assert @issue.recipients.include?(project_recipient)
1723 assert @issue.recipients.include?(project_recipient)
1708 end
1724 end
1709 end
1725 end
1710
1726
1711 should "include the author if the author is active" do
1727 should "include the author if the author is active" do
1712 assert @issue.author, "No author set for Issue"
1728 assert @issue.author, "No author set for Issue"
1713 assert @issue.recipients.include?(@issue.author.mail)
1729 assert @issue.recipients.include?(@issue.author.mail)
1714 end
1730 end
1715
1731
1716 should "include the assigned to user if the assigned to user is active" do
1732 should "include the assigned to user if the assigned to user is active" do
1717 assert @issue.assigned_to, "No assigned_to set for Issue"
1733 assert @issue.assigned_to, "No assigned_to set for Issue"
1718 assert @issue.recipients.include?(@issue.assigned_to.mail)
1734 assert @issue.recipients.include?(@issue.assigned_to.mail)
1719 end
1735 end
1720
1736
1721 should "not include users who opt out of all email" do
1737 should "not include users who opt out of all email" do
1722 @author.update_attribute(:mail_notification, :none)
1738 @author.update_attribute(:mail_notification, :none)
1723
1739
1724 assert !@issue.recipients.include?(@issue.author.mail)
1740 assert !@issue.recipients.include?(@issue.author.mail)
1725 end
1741 end
1726
1742
1727 should "not include the issue author if they are only notified of assigned issues" do
1743 should "not include the issue author if they are only notified of assigned issues" do
1728 @author.update_attribute(:mail_notification, :only_assigned)
1744 @author.update_attribute(:mail_notification, :only_assigned)
1729
1745
1730 assert !@issue.recipients.include?(@issue.author.mail)
1746 assert !@issue.recipients.include?(@issue.author.mail)
1731 end
1747 end
1732
1748
1733 should "not include the assigned user if they are only notified of owned issues" do
1749 should "not include the assigned user if they are only notified of owned issues" do
1734 @assignee.update_attribute(:mail_notification, :only_owner)
1750 @assignee.update_attribute(:mail_notification, :only_owner)
1735
1751
1736 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1752 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1737 end
1753 end
1738 end
1754 end
1739
1755
1740 def test_last_journal_id_with_journals_should_return_the_journal_id
1756 def test_last_journal_id_with_journals_should_return_the_journal_id
1741 assert_equal 2, Issue.find(1).last_journal_id
1757 assert_equal 2, Issue.find(1).last_journal_id
1742 end
1758 end
1743
1759
1744 def test_last_journal_id_without_journals_should_return_nil
1760 def test_last_journal_id_without_journals_should_return_nil
1745 assert_nil Issue.find(3).last_journal_id
1761 assert_nil Issue.find(3).last_journal_id
1746 end
1762 end
1747
1763
1748 def test_journals_after_should_return_journals_with_greater_id
1764 def test_journals_after_should_return_journals_with_greater_id
1749 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1765 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1750 assert_equal [], Issue.find(1).journals_after('2')
1766 assert_equal [], Issue.find(1).journals_after('2')
1751 end
1767 end
1752
1768
1753 def test_journals_after_with_blank_arg_should_return_all_journals
1769 def test_journals_after_with_blank_arg_should_return_all_journals
1754 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1770 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1755 end
1771 end
1756 end
1772 end
General Comments 0
You need to be logged in to leave comments. Login now