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