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