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