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