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