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