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