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