##// END OF EJS Templates
Use fixtures generator....
Jean-Philippe Lang -
r8175:3ce595b80677
parent child
Show More
@@ -1,1167 +1,1163
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 :trackers, :projects_trackers,
22 :trackers, :projects_trackers,
23 :enabled_modules,
23 :enabled_modules,
24 :versions,
24 :versions,
25 :issue_statuses, :issue_categories, :issue_relations, :workflows,
25 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :enumerations,
26 :enumerations,
27 :issues,
27 :issues,
28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :time_entries
29 :time_entries
30
30
31 def test_create
31 def test_create
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
33 :status_id => 1, :priority => IssuePriority.all.first,
33 :status_id => 1, :priority => IssuePriority.all.first,
34 :subject => 'test_create',
34 :subject => 'test_create',
35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
36 assert issue.save
36 assert issue.save
37 issue.reload
37 issue.reload
38 assert_equal 1.5, issue.estimated_hours
38 assert_equal 1.5, issue.estimated_hours
39 end
39 end
40
40
41 def test_create_minimal
41 def test_create_minimal
42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
43 :status_id => 1, :priority => IssuePriority.all.first,
43 :status_id => 1, :priority => IssuePriority.all.first,
44 :subject => 'test_create')
44 :subject => 'test_create')
45 assert issue.save
45 assert issue.save
46 assert issue.description.nil?
46 assert issue.description.nil?
47 end
47 end
48
48
49 def test_create_with_required_custom_field
49 def test_create_with_required_custom_field
50 field = IssueCustomField.find_by_name('Database')
50 field = IssueCustomField.find_by_name('Database')
51 field.update_attribute(:is_required, true)
51 field.update_attribute(:is_required, true)
52
52
53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
54 :status_id => 1, :subject => 'test_create',
54 :status_id => 1, :subject => 'test_create',
55 :description => 'IssueTest#test_create_with_required_custom_field')
55 :description => 'IssueTest#test_create_with_required_custom_field')
56 assert issue.available_custom_fields.include?(field)
56 assert issue.available_custom_fields.include?(field)
57 # No value for the custom field
57 # No value for the custom field
58 assert !issue.save
58 assert !issue.save
59 assert_equal I18n.translate('activerecord.errors.messages.invalid'),
59 assert_equal I18n.translate('activerecord.errors.messages.invalid'),
60 issue.errors[:custom_values].to_s
60 issue.errors[:custom_values].to_s
61 # Blank value
61 # Blank value
62 issue.custom_field_values = { field.id => '' }
62 issue.custom_field_values = { field.id => '' }
63 assert !issue.save
63 assert !issue.save
64 assert_equal I18n.translate('activerecord.errors.messages.invalid'),
64 assert_equal I18n.translate('activerecord.errors.messages.invalid'),
65 issue.errors[:custom_values].to_s
65 issue.errors[:custom_values].to_s
66 # Invalid value
66 # Invalid value
67 issue.custom_field_values = { field.id => 'SQLServer' }
67 issue.custom_field_values = { field.id => 'SQLServer' }
68 assert !issue.save
68 assert !issue.save
69 assert_equal I18n.translate('activerecord.errors.messages.invalid'),
69 assert_equal I18n.translate('activerecord.errors.messages.invalid'),
70 issue.errors[:custom_values].to_s
70 issue.errors[:custom_values].to_s
71 # Valid value
71 # Valid value
72 issue.custom_field_values = { field.id => 'PostgreSQL' }
72 issue.custom_field_values = { field.id => 'PostgreSQL' }
73 assert issue.save
73 assert issue.save
74 issue.reload
74 issue.reload
75 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
75 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
76 end
76 end
77
77
78 def test_create_with_group_assignment
78 def test_create_with_group_assignment
79 with_settings :issue_group_assignment => '1' do
79 with_settings :issue_group_assignment => '1' do
80 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
80 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
81 :subject => 'Group assignment',
81 :subject => 'Group assignment',
82 :assigned_to_id => 11).save
82 :assigned_to_id => 11).save
83 issue = Issue.first(:order => 'id DESC')
83 issue = Issue.first(:order => 'id DESC')
84 assert_kind_of Group, issue.assigned_to
84 assert_kind_of Group, issue.assigned_to
85 assert_equal Group.find(11), issue.assigned_to
85 assert_equal Group.find(11), issue.assigned_to
86 end
86 end
87 end
87 end
88
88
89 def assert_visibility_match(user, issues)
89 def assert_visibility_match(user, issues)
90 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
90 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
91 end
91 end
92
92
93 def test_visible_scope_for_anonymous
93 def test_visible_scope_for_anonymous
94 # Anonymous user should see issues of public projects only
94 # Anonymous user should see issues of public projects only
95 issues = Issue.visible(User.anonymous).all
95 issues = Issue.visible(User.anonymous).all
96 assert issues.any?
96 assert issues.any?
97 assert_nil issues.detect {|issue| !issue.project.is_public?}
97 assert_nil issues.detect {|issue| !issue.project.is_public?}
98 assert_nil issues.detect {|issue| issue.is_private?}
98 assert_nil issues.detect {|issue| issue.is_private?}
99 assert_visibility_match User.anonymous, issues
99 assert_visibility_match User.anonymous, issues
100 end
100 end
101
101
102 def test_visible_scope_for_anonymous_with_own_issues_visibility
102 def test_visible_scope_for_anonymous_with_own_issues_visibility
103 Role.anonymous.update_attribute :issues_visibility, 'own'
103 Role.anonymous.update_attribute :issues_visibility, 'own'
104 Issue.create!(:project_id => 1, :tracker_id => 1,
104 Issue.create!(:project_id => 1, :tracker_id => 1,
105 :author_id => User.anonymous.id,
105 :author_id => User.anonymous.id,
106 :subject => 'Issue by anonymous')
106 :subject => 'Issue by anonymous')
107
107
108 issues = Issue.visible(User.anonymous).all
108 issues = Issue.visible(User.anonymous).all
109 assert issues.any?
109 assert issues.any?
110 assert_nil issues.detect {|issue| issue.author != User.anonymous}
110 assert_nil issues.detect {|issue| issue.author != User.anonymous}
111 assert_visibility_match User.anonymous, issues
111 assert_visibility_match User.anonymous, issues
112 end
112 end
113
113
114 def test_visible_scope_for_anonymous_without_view_issues_permissions
114 def test_visible_scope_for_anonymous_without_view_issues_permissions
115 # Anonymous user should not see issues without permission
115 # Anonymous user should not see issues without permission
116 Role.anonymous.remove_permission!(:view_issues)
116 Role.anonymous.remove_permission!(:view_issues)
117 issues = Issue.visible(User.anonymous).all
117 issues = Issue.visible(User.anonymous).all
118 assert issues.empty?
118 assert issues.empty?
119 assert_visibility_match User.anonymous, issues
119 assert_visibility_match User.anonymous, issues
120 end
120 end
121
121
122 def test_visible_scope_for_non_member
122 def test_visible_scope_for_non_member
123 user = User.find(9)
123 user = User.find(9)
124 assert user.projects.empty?
124 assert user.projects.empty?
125 # Non member user should see issues of public projects only
125 # Non member user should see issues of public projects only
126 issues = Issue.visible(user).all
126 issues = Issue.visible(user).all
127 assert issues.any?
127 assert issues.any?
128 assert_nil issues.detect {|issue| !issue.project.is_public?}
128 assert_nil issues.detect {|issue| !issue.project.is_public?}
129 assert_nil issues.detect {|issue| issue.is_private?}
129 assert_nil issues.detect {|issue| issue.is_private?}
130 assert_visibility_match user, issues
130 assert_visibility_match user, issues
131 end
131 end
132
132
133 def test_visible_scope_for_non_member_with_own_issues_visibility
133 def test_visible_scope_for_non_member_with_own_issues_visibility
134 Role.non_member.update_attribute :issues_visibility, 'own'
134 Role.non_member.update_attribute :issues_visibility, 'own'
135 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
135 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
136 user = User.find(9)
136 user = User.find(9)
137
137
138 issues = Issue.visible(user).all
138 issues = Issue.visible(user).all
139 assert issues.any?
139 assert issues.any?
140 assert_nil issues.detect {|issue| issue.author != user}
140 assert_nil issues.detect {|issue| issue.author != user}
141 assert_visibility_match user, issues
141 assert_visibility_match user, issues
142 end
142 end
143
143
144 def test_visible_scope_for_non_member_without_view_issues_permissions
144 def test_visible_scope_for_non_member_without_view_issues_permissions
145 # Non member user should not see issues without permission
145 # Non member user should not see issues without permission
146 Role.non_member.remove_permission!(:view_issues)
146 Role.non_member.remove_permission!(:view_issues)
147 user = User.find(9)
147 user = User.find(9)
148 assert user.projects.empty?
148 assert user.projects.empty?
149 issues = Issue.visible(user).all
149 issues = Issue.visible(user).all
150 assert issues.empty?
150 assert issues.empty?
151 assert_visibility_match user, issues
151 assert_visibility_match user, issues
152 end
152 end
153
153
154 def test_visible_scope_for_member
154 def test_visible_scope_for_member
155 user = User.find(9)
155 user = User.find(9)
156 # User should see issues of projects for which he has view_issues permissions only
156 # User should see issues of projects for which he has view_issues permissions only
157 Role.non_member.remove_permission!(:view_issues)
157 Role.non_member.remove_permission!(:view_issues)
158 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
158 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
159 issues = Issue.visible(user).all
159 issues = Issue.visible(user).all
160 assert issues.any?
160 assert issues.any?
161 assert_nil issues.detect {|issue| issue.project_id != 3}
161 assert_nil issues.detect {|issue| issue.project_id != 3}
162 assert_nil issues.detect {|issue| issue.is_private?}
162 assert_nil issues.detect {|issue| issue.is_private?}
163 assert_visibility_match user, issues
163 assert_visibility_match user, issues
164 end
164 end
165
165
166 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
166 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
167 user = User.find(8)
167 user = User.find(8)
168 assert user.groups.any?
168 assert user.groups.any?
169 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
169 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
170 Role.non_member.remove_permission!(:view_issues)
170 Role.non_member.remove_permission!(:view_issues)
171
171
172 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
172 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
173 :status_id => 1, :priority => IssuePriority.all.first,
173 :status_id => 1, :priority => IssuePriority.all.first,
174 :subject => 'Assignment test',
174 :subject => 'Assignment test',
175 :assigned_to => user.groups.first,
175 :assigned_to => user.groups.first,
176 :is_private => true)
176 :is_private => true)
177
177
178 Role.find(2).update_attribute :issues_visibility, 'default'
178 Role.find(2).update_attribute :issues_visibility, 'default'
179 issues = Issue.visible(User.find(8)).all
179 issues = Issue.visible(User.find(8)).all
180 assert issues.any?
180 assert issues.any?
181 assert issues.include?(issue)
181 assert issues.include?(issue)
182
182
183 Role.find(2).update_attribute :issues_visibility, 'own'
183 Role.find(2).update_attribute :issues_visibility, 'own'
184 issues = Issue.visible(User.find(8)).all
184 issues = Issue.visible(User.find(8)).all
185 assert issues.any?
185 assert issues.any?
186 assert issues.include?(issue)
186 assert issues.include?(issue)
187 end
187 end
188
188
189 def test_visible_scope_for_admin
189 def test_visible_scope_for_admin
190 user = User.find(1)
190 user = User.find(1)
191 user.members.each(&:destroy)
191 user.members.each(&:destroy)
192 assert user.projects.empty?
192 assert user.projects.empty?
193 issues = Issue.visible(user).all
193 issues = Issue.visible(user).all
194 assert issues.any?
194 assert issues.any?
195 # Admin should see issues on private projects that he does not belong to
195 # Admin should see issues on private projects that he does not belong to
196 assert issues.detect {|issue| !issue.project.is_public?}
196 assert issues.detect {|issue| !issue.project.is_public?}
197 # Admin should see private issues of other users
197 # Admin should see private issues of other users
198 assert issues.detect {|issue| issue.is_private? && issue.author != user}
198 assert issues.detect {|issue| issue.is_private? && issue.author != user}
199 assert_visibility_match user, issues
199 assert_visibility_match user, issues
200 end
200 end
201
201
202 def test_visible_scope_with_project
202 def test_visible_scope_with_project
203 project = Project.find(1)
203 project = Project.find(1)
204 issues = Issue.visible(User.find(2), :project => project).all
204 issues = Issue.visible(User.find(2), :project => project).all
205 projects = issues.collect(&:project).uniq
205 projects = issues.collect(&:project).uniq
206 assert_equal 1, projects.size
206 assert_equal 1, projects.size
207 assert_equal project, projects.first
207 assert_equal project, projects.first
208 end
208 end
209
209
210 def test_visible_scope_with_project_and_subprojects
210 def test_visible_scope_with_project_and_subprojects
211 project = Project.find(1)
211 project = Project.find(1)
212 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
212 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
213 projects = issues.collect(&:project).uniq
213 projects = issues.collect(&:project).uniq
214 assert projects.size > 1
214 assert projects.size > 1
215 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
215 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
216 end
216 end
217
217
218 def test_visible_and_nested_set_scopes
218 def test_visible_and_nested_set_scopes
219 assert_equal 0, Issue.find(1).descendants.visible.all.size
219 assert_equal 0, Issue.find(1).descendants.visible.all.size
220 end
220 end
221
221
222 def test_open_scope
222 def test_open_scope
223 issues = Issue.open.all
223 issues = Issue.open.all
224 assert_nil issues.detect(&:closed?)
224 assert_nil issues.detect(&:closed?)
225 end
225 end
226
226
227 def test_open_scope_with_arg
227 def test_open_scope_with_arg
228 issues = Issue.open(false).all
228 issues = Issue.open(false).all
229 assert_equal issues, issues.select(&:closed?)
229 assert_equal issues, issues.select(&:closed?)
230 end
230 end
231
231
232 def test_errors_full_messages_should_include_custom_fields_errors
232 def test_errors_full_messages_should_include_custom_fields_errors
233 field = IssueCustomField.find_by_name('Database')
233 field = IssueCustomField.find_by_name('Database')
234
234
235 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
235 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
236 :status_id => 1, :subject => 'test_create',
236 :status_id => 1, :subject => 'test_create',
237 :description => 'IssueTest#test_create_with_required_custom_field')
237 :description => 'IssueTest#test_create_with_required_custom_field')
238 assert issue.available_custom_fields.include?(field)
238 assert issue.available_custom_fields.include?(field)
239 # Invalid value
239 # Invalid value
240 issue.custom_field_values = { field.id => 'SQLServer' }
240 issue.custom_field_values = { field.id => 'SQLServer' }
241
241
242 assert !issue.valid?
242 assert !issue.valid?
243 assert_equal 1, issue.errors.full_messages.size
243 assert_equal 1, issue.errors.full_messages.size
244 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
244 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
245 issue.errors.full_messages.first
245 issue.errors.full_messages.first
246 end
246 end
247
247
248 def test_update_issue_with_required_custom_field
248 def test_update_issue_with_required_custom_field
249 field = IssueCustomField.find_by_name('Database')
249 field = IssueCustomField.find_by_name('Database')
250 field.update_attribute(:is_required, true)
250 field.update_attribute(:is_required, true)
251
251
252 issue = Issue.find(1)
252 issue = Issue.find(1)
253 assert_nil issue.custom_value_for(field)
253 assert_nil issue.custom_value_for(field)
254 assert issue.available_custom_fields.include?(field)
254 assert issue.available_custom_fields.include?(field)
255 # No change to custom values, issue can be saved
255 # No change to custom values, issue can be saved
256 assert issue.save
256 assert issue.save
257 # Blank value
257 # Blank value
258 issue.custom_field_values = { field.id => '' }
258 issue.custom_field_values = { field.id => '' }
259 assert !issue.save
259 assert !issue.save
260 # Valid value
260 # Valid value
261 issue.custom_field_values = { field.id => 'PostgreSQL' }
261 issue.custom_field_values = { field.id => 'PostgreSQL' }
262 assert issue.save
262 assert issue.save
263 issue.reload
263 issue.reload
264 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
264 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
265 end
265 end
266
266
267 def test_should_not_update_attributes_if_custom_fields_validation_fails
267 def test_should_not_update_attributes_if_custom_fields_validation_fails
268 issue = Issue.find(1)
268 issue = Issue.find(1)
269 field = IssueCustomField.find_by_name('Database')
269 field = IssueCustomField.find_by_name('Database')
270 assert issue.available_custom_fields.include?(field)
270 assert issue.available_custom_fields.include?(field)
271
271
272 issue.custom_field_values = { field.id => 'Invalid' }
272 issue.custom_field_values = { field.id => 'Invalid' }
273 issue.subject = 'Should be not be saved'
273 issue.subject = 'Should be not be saved'
274 assert !issue.save
274 assert !issue.save
275
275
276 issue.reload
276 issue.reload
277 assert_equal "Can't print recipes", issue.subject
277 assert_equal "Can't print recipes", issue.subject
278 end
278 end
279
279
280 def test_should_not_recreate_custom_values_objects_on_update
280 def test_should_not_recreate_custom_values_objects_on_update
281 field = IssueCustomField.find_by_name('Database')
281 field = IssueCustomField.find_by_name('Database')
282
282
283 issue = Issue.find(1)
283 issue = Issue.find(1)
284 issue.custom_field_values = { field.id => 'PostgreSQL' }
284 issue.custom_field_values = { field.id => 'PostgreSQL' }
285 assert issue.save
285 assert issue.save
286 custom_value = issue.custom_value_for(field)
286 custom_value = issue.custom_value_for(field)
287 issue.reload
287 issue.reload
288 issue.custom_field_values = { field.id => 'MySQL' }
288 issue.custom_field_values = { field.id => 'MySQL' }
289 assert issue.save
289 assert issue.save
290 issue.reload
290 issue.reload
291 assert_equal custom_value.id, issue.custom_value_for(field).id
291 assert_equal custom_value.id, issue.custom_value_for(field).id
292 end
292 end
293
293
294 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
294 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
295 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'Test', :custom_field_values => {'2' => 'Test'})
295 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'Test', :custom_field_values => {'2' => 'Test'})
296 assert !Tracker.find(2).custom_field_ids.include?(2)
296 assert !Tracker.find(2).custom_field_ids.include?(2)
297
297
298 issue = Issue.find(issue.id)
298 issue = Issue.find(issue.id)
299 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
299 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
300
300
301 issue = Issue.find(issue.id)
301 issue = Issue.find(issue.id)
302 custom_value = issue.custom_value_for(2)
302 custom_value = issue.custom_value_for(2)
303 assert_not_nil custom_value
303 assert_not_nil custom_value
304 assert_equal 'Test', custom_value.value
304 assert_equal 'Test', custom_value.value
305 end
305 end
306
306
307 def test_assigning_tracker_id_should_reload_custom_fields_values
307 def test_assigning_tracker_id_should_reload_custom_fields_values
308 issue = Issue.new(:project => Project.find(1))
308 issue = Issue.new(:project => Project.find(1))
309 assert issue.custom_field_values.empty?
309 assert issue.custom_field_values.empty?
310 issue.tracker_id = 1
310 issue.tracker_id = 1
311 assert issue.custom_field_values.any?
311 assert issue.custom_field_values.any?
312 end
312 end
313
313
314 def test_assigning_attributes_should_assign_project_and_tracker_first
314 def test_assigning_attributes_should_assign_project_and_tracker_first
315 seq = sequence('seq')
315 seq = sequence('seq')
316 issue = Issue.new
316 issue = Issue.new
317 issue.expects(:project_id=).in_sequence(seq)
317 issue.expects(:project_id=).in_sequence(seq)
318 issue.expects(:tracker_id=).in_sequence(seq)
318 issue.expects(:tracker_id=).in_sequence(seq)
319 issue.expects(:subject=).in_sequence(seq)
319 issue.expects(:subject=).in_sequence(seq)
320 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
320 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
321 end
321 end
322
322
323 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
323 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
324 attributes = ActiveSupport::OrderedHash.new
324 attributes = ActiveSupport::OrderedHash.new
325 attributes['custom_field_values'] = { '1' => 'MySQL' }
325 attributes['custom_field_values'] = { '1' => 'MySQL' }
326 attributes['tracker_id'] = '1'
326 attributes['tracker_id'] = '1'
327 issue = Issue.new(:project => Project.find(1))
327 issue = Issue.new(:project => Project.find(1))
328 issue.attributes = attributes
328 issue.attributes = attributes
329 assert_not_nil issue.custom_value_for(1)
329 assert_not_nil issue.custom_value_for(1)
330 assert_equal 'MySQL', issue.custom_value_for(1).value
330 assert_equal 'MySQL', issue.custom_value_for(1).value
331 end
331 end
332
332
333 def test_should_update_issue_with_disabled_tracker
333 def test_should_update_issue_with_disabled_tracker
334 p = Project.find(1)
334 p = Project.find(1)
335 issue = Issue.find(1)
335 issue = Issue.find(1)
336
336
337 p.trackers.delete(issue.tracker)
337 p.trackers.delete(issue.tracker)
338 assert !p.trackers.include?(issue.tracker)
338 assert !p.trackers.include?(issue.tracker)
339
339
340 issue.reload
340 issue.reload
341 issue.subject = 'New subject'
341 issue.subject = 'New subject'
342 assert issue.save
342 assert issue.save
343 end
343 end
344
344
345 def test_should_not_set_a_disabled_tracker
345 def test_should_not_set_a_disabled_tracker
346 p = Project.find(1)
346 p = Project.find(1)
347 p.trackers.delete(Tracker.find(2))
347 p.trackers.delete(Tracker.find(2))
348
348
349 issue = Issue.find(1)
349 issue = Issue.find(1)
350 issue.tracker_id = 2
350 issue.tracker_id = 2
351 issue.subject = 'New subject'
351 issue.subject = 'New subject'
352 assert !issue.save
352 assert !issue.save
353 assert_not_nil issue.errors[:tracker_id]
353 assert_not_nil issue.errors[:tracker_id]
354 end
354 end
355
355
356 def test_category_based_assignment
356 def test_category_based_assignment
357 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
357 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
358 :status_id => 1, :priority => IssuePriority.all.first,
358 :status_id => 1, :priority => IssuePriority.all.first,
359 :subject => 'Assignment test',
359 :subject => 'Assignment test',
360 :description => 'Assignment test', :category_id => 1)
360 :description => 'Assignment test', :category_id => 1)
361 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
361 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
362 end
362 end
363
363
364 def test_new_statuses_allowed_to
364 def test_new_statuses_allowed_to
365 Workflow.delete_all
365 Workflow.delete_all
366
366
367 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
367 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
368 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
368 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
369 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
369 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
370 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
370 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
371 status = IssueStatus.find(1)
371 status = IssueStatus.find(1)
372 role = Role.find(1)
372 role = Role.find(1)
373 tracker = Tracker.find(1)
373 tracker = Tracker.find(1)
374 user = User.find(2)
374 user = User.find(2)
375
375
376 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
376 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
377 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
377 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
378
378
379 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
379 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
380 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
380 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
381
381
382 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
382 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
383 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
383 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
384
384
385 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
385 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
386 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
386 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
387 end
387 end
388
388
389 def test_copy
389 def test_copy
390 issue = Issue.new.copy_from(1)
390 issue = Issue.new.copy_from(1)
391 assert issue.save
391 assert issue.save
392 issue.reload
392 issue.reload
393 orig = Issue.find(1)
393 orig = Issue.find(1)
394 assert_equal orig.subject, issue.subject
394 assert_equal orig.subject, issue.subject
395 assert_equal orig.tracker, issue.tracker
395 assert_equal orig.tracker, issue.tracker
396 assert_equal "125", issue.custom_value_for(2).value
396 assert_equal "125", issue.custom_value_for(2).value
397 end
397 end
398
398
399 def test_copy_should_copy_status
399 def test_copy_should_copy_status
400 orig = Issue.find(8)
400 orig = Issue.find(8)
401 assert orig.status != IssueStatus.default
401 assert orig.status != IssueStatus.default
402
402
403 issue = Issue.new.copy_from(orig)
403 issue = Issue.new.copy_from(orig)
404 assert issue.save
404 assert issue.save
405 issue.reload
405 issue.reload
406 assert_equal orig.status, issue.status
406 assert_equal orig.status, issue.status
407 end
407 end
408
408
409 def test_should_close_duplicates
409 def test_should_close_duplicates
410 # Create 3 issues
410 # Create 3 issues
411 project = Project.find(1)
411 project = Project.find(1)
412 issue1 = Issue.generate_for_project!(project)
412 issue1 = Issue.generate_for_project!(project)
413 issue2 = Issue.generate_for_project!(project)
413 issue2 = Issue.generate_for_project!(project)
414 issue3 = Issue.generate_for_project!(project)
414 issue3 = Issue.generate_for_project!(project)
415
415
416 # 2 is a dupe of 1
416 # 2 is a dupe of 1
417 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
417 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
418 # And 3 is a dupe of 2
418 # And 3 is a dupe of 2
419 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
419 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
420 # And 3 is a dupe of 1 (circular duplicates)
420 # And 3 is a dupe of 1 (circular duplicates)
421 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
421 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
422
422
423 assert issue1.reload.duplicates.include?(issue2)
423 assert issue1.reload.duplicates.include?(issue2)
424
424
425 # Closing issue 1
425 # Closing issue 1
426 issue1.init_journal(User.find(:first), "Closing issue1")
426 issue1.init_journal(User.find(:first), "Closing issue1")
427 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
427 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
428 assert issue1.save
428 assert issue1.save
429 # 2 and 3 should be also closed
429 # 2 and 3 should be also closed
430 assert issue2.reload.closed?
430 assert issue2.reload.closed?
431 assert issue3.reload.closed?
431 assert issue3.reload.closed?
432 end
432 end
433
433
434 def test_should_not_close_duplicated_issue
434 def test_should_not_close_duplicated_issue
435 # Create 3 issues
435 project = Project.find(1)
436 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
436 issue1 = Issue.generate_for_project!(project)
437 :status_id => 1, :priority => IssuePriority.all.first,
437 issue2 = Issue.generate_for_project!(project)
438 :subject => 'Duplicates test', :description => 'Duplicates test')
439 assert issue1.save
440 issue2 = issue1.clone
441 assert issue2.save
442
438
443 # 2 is a dupe of 1
439 # 2 is a dupe of 1
444 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
440 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
445 # 2 is a dup of 1 but 1 is not a duplicate of 2
441 # 2 is a dup of 1 but 1 is not a duplicate of 2
446 assert !issue2.reload.duplicates.include?(issue1)
442 assert !issue2.reload.duplicates.include?(issue1)
447
443
448 # Closing issue 2
444 # Closing issue 2
449 issue2.init_journal(User.find(:first), "Closing issue2")
445 issue2.init_journal(User.find(:first), "Closing issue2")
450 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
446 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
451 assert issue2.save
447 assert issue2.save
452 # 1 should not be also closed
448 # 1 should not be also closed
453 assert !issue1.reload.closed?
449 assert !issue1.reload.closed?
454 end
450 end
455
451
456 def test_assignable_versions
452 def test_assignable_versions
457 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
453 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
458 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
454 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
459 end
455 end
460
456
461 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
457 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
462 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
458 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
463 assert !issue.save
459 assert !issue.save
464 assert_not_nil issue.errors[:fixed_version_id]
460 assert_not_nil issue.errors[:fixed_version_id]
465 end
461 end
466
462
467 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
463 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
468 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
464 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
469 assert !issue.save
465 assert !issue.save
470 assert_not_nil issue.errors[:fixed_version_id]
466 assert_not_nil issue.errors[:fixed_version_id]
471 end
467 end
472
468
473 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
469 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
474 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
470 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
475 assert issue.save
471 assert issue.save
476 end
472 end
477
473
478 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
474 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
479 issue = Issue.find(11)
475 issue = Issue.find(11)
480 assert_equal 'closed', issue.fixed_version.status
476 assert_equal 'closed', issue.fixed_version.status
481 issue.subject = 'Subject changed'
477 issue.subject = 'Subject changed'
482 assert issue.save
478 assert issue.save
483 end
479 end
484
480
485 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
481 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
486 issue = Issue.find(11)
482 issue = Issue.find(11)
487 issue.status_id = 1
483 issue.status_id = 1
488 assert !issue.save
484 assert !issue.save
489 assert_not_nil issue.errors[:base]
485 assert_not_nil issue.errors[:base]
490 end
486 end
491
487
492 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
488 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
493 issue = Issue.find(11)
489 issue = Issue.find(11)
494 issue.status_id = 1
490 issue.status_id = 1
495 issue.fixed_version_id = 3
491 issue.fixed_version_id = 3
496 assert issue.save
492 assert issue.save
497 end
493 end
498
494
499 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
495 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
500 issue = Issue.find(12)
496 issue = Issue.find(12)
501 assert_equal 'locked', issue.fixed_version.status
497 assert_equal 'locked', issue.fixed_version.status
502 issue.status_id = 1
498 issue.status_id = 1
503 assert issue.save
499 assert issue.save
504 end
500 end
505
501
506 def test_move_to_another_project_with_same_category
502 def test_move_to_another_project_with_same_category
507 issue = Issue.find(1)
503 issue = Issue.find(1)
508 assert issue.move_to_project(Project.find(2))
504 assert issue.move_to_project(Project.find(2))
509 issue.reload
505 issue.reload
510 assert_equal 2, issue.project_id
506 assert_equal 2, issue.project_id
511 # Category changes
507 # Category changes
512 assert_equal 4, issue.category_id
508 assert_equal 4, issue.category_id
513 # Make sure time entries were move to the target project
509 # Make sure time entries were move to the target project
514 assert_equal 2, issue.time_entries.first.project_id
510 assert_equal 2, issue.time_entries.first.project_id
515 end
511 end
516
512
517 def test_move_to_another_project_without_same_category
513 def test_move_to_another_project_without_same_category
518 issue = Issue.find(2)
514 issue = Issue.find(2)
519 assert issue.move_to_project(Project.find(2))
515 assert issue.move_to_project(Project.find(2))
520 issue.reload
516 issue.reload
521 assert_equal 2, issue.project_id
517 assert_equal 2, issue.project_id
522 # Category cleared
518 # Category cleared
523 assert_nil issue.category_id
519 assert_nil issue.category_id
524 end
520 end
525
521
526 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
522 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
527 issue = Issue.find(1)
523 issue = Issue.find(1)
528 issue.update_attribute(:fixed_version_id, 1)
524 issue.update_attribute(:fixed_version_id, 1)
529 assert issue.move_to_project(Project.find(2))
525 assert issue.move_to_project(Project.find(2))
530 issue.reload
526 issue.reload
531 assert_equal 2, issue.project_id
527 assert_equal 2, issue.project_id
532 # Cleared fixed_version
528 # Cleared fixed_version
533 assert_equal nil, issue.fixed_version
529 assert_equal nil, issue.fixed_version
534 end
530 end
535
531
536 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
532 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
537 issue = Issue.find(1)
533 issue = Issue.find(1)
538 issue.update_attribute(:fixed_version_id, 4)
534 issue.update_attribute(:fixed_version_id, 4)
539 assert issue.move_to_project(Project.find(5))
535 assert issue.move_to_project(Project.find(5))
540 issue.reload
536 issue.reload
541 assert_equal 5, issue.project_id
537 assert_equal 5, issue.project_id
542 # Keep fixed_version
538 # Keep fixed_version
543 assert_equal 4, issue.fixed_version_id
539 assert_equal 4, issue.fixed_version_id
544 end
540 end
545
541
546 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
542 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
547 issue = Issue.find(1)
543 issue = Issue.find(1)
548 issue.update_attribute(:fixed_version_id, 1)
544 issue.update_attribute(:fixed_version_id, 1)
549 assert issue.move_to_project(Project.find(5))
545 assert issue.move_to_project(Project.find(5))
550 issue.reload
546 issue.reload
551 assert_equal 5, issue.project_id
547 assert_equal 5, issue.project_id
552 # Cleared fixed_version
548 # Cleared fixed_version
553 assert_equal nil, issue.fixed_version
549 assert_equal nil, issue.fixed_version
554 end
550 end
555
551
556 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
552 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
557 issue = Issue.find(1)
553 issue = Issue.find(1)
558 issue.update_attribute(:fixed_version_id, 7)
554 issue.update_attribute(:fixed_version_id, 7)
559 assert issue.move_to_project(Project.find(2))
555 assert issue.move_to_project(Project.find(2))
560 issue.reload
556 issue.reload
561 assert_equal 2, issue.project_id
557 assert_equal 2, issue.project_id
562 # Keep fixed_version
558 # Keep fixed_version
563 assert_equal 7, issue.fixed_version_id
559 assert_equal 7, issue.fixed_version_id
564 end
560 end
565
561
566 def test_move_to_another_project_with_disabled_tracker
562 def test_move_to_another_project_with_disabled_tracker
567 issue = Issue.find(1)
563 issue = Issue.find(1)
568 target = Project.find(2)
564 target = Project.find(2)
569 target.tracker_ids = [3]
565 target.tracker_ids = [3]
570 target.save
566 target.save
571 assert_equal false, issue.move_to_project(target)
567 assert_equal false, issue.move_to_project(target)
572 issue.reload
568 issue.reload
573 assert_equal 1, issue.project_id
569 assert_equal 1, issue.project_id
574 end
570 end
575
571
576 def test_copy_to_the_same_project
572 def test_copy_to_the_same_project
577 issue = Issue.find(1)
573 issue = Issue.find(1)
578 copy = nil
574 copy = nil
579 assert_difference 'Issue.count' do
575 assert_difference 'Issue.count' do
580 copy = issue.move_to_project(issue.project, nil, :copy => true)
576 copy = issue.move_to_project(issue.project, nil, :copy => true)
581 end
577 end
582 assert_kind_of Issue, copy
578 assert_kind_of Issue, copy
583 assert_equal issue.project, copy.project
579 assert_equal issue.project, copy.project
584 assert_equal "125", copy.custom_value_for(2).value
580 assert_equal "125", copy.custom_value_for(2).value
585 end
581 end
586
582
587 def test_copy_to_another_project_and_tracker
583 def test_copy_to_another_project_and_tracker
588 issue = Issue.find(1)
584 issue = Issue.find(1)
589 copy = nil
585 copy = nil
590 assert_difference 'Issue.count' do
586 assert_difference 'Issue.count' do
591 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
587 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
592 end
588 end
593 copy.reload
589 copy.reload
594 assert_kind_of Issue, copy
590 assert_kind_of Issue, copy
595 assert_equal Project.find(3), copy.project
591 assert_equal Project.find(3), copy.project
596 assert_equal Tracker.find(2), copy.tracker
592 assert_equal Tracker.find(2), copy.tracker
597 # Custom field #2 is not associated with target tracker
593 # Custom field #2 is not associated with target tracker
598 assert_nil copy.custom_value_for(2)
594 assert_nil copy.custom_value_for(2)
599 end
595 end
600
596
601 context "#move_to_project" do
597 context "#move_to_project" do
602 context "as a copy" do
598 context "as a copy" do
603 setup do
599 setup do
604 @issue = Issue.find(1)
600 @issue = Issue.find(1)
605 @copy = nil
601 @copy = nil
606 end
602 end
607
603
608 should "not create a journal" do
604 should "not create a journal" do
609 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
605 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
610 assert_equal 0, @copy.reload.journals.size
606 assert_equal 0, @copy.reload.journals.size
611 end
607 end
612
608
613 should "allow assigned_to changes" do
609 should "allow assigned_to changes" do
614 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
610 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
615 assert_equal 3, @copy.assigned_to_id
611 assert_equal 3, @copy.assigned_to_id
616 end
612 end
617
613
618 should "allow status changes" do
614 should "allow status changes" do
619 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
615 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
620 assert_equal 2, @copy.status_id
616 assert_equal 2, @copy.status_id
621 end
617 end
622
618
623 should "allow start date changes" do
619 should "allow start date changes" do
624 date = Date.today
620 date = Date.today
625 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
621 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
626 assert_equal date, @copy.start_date
622 assert_equal date, @copy.start_date
627 end
623 end
628
624
629 should "allow due date changes" do
625 should "allow due date changes" do
630 date = Date.today
626 date = Date.today
631 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
627 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
632
628
633 assert_equal date, @copy.due_date
629 assert_equal date, @copy.due_date
634 end
630 end
635
631
636 should "set current user as author" do
632 should "set current user as author" do
637 User.current = User.find(9)
633 User.current = User.find(9)
638 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
634 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
639
635
640 assert_equal User.current, @copy.author
636 assert_equal User.current, @copy.author
641 end
637 end
642
638
643 should "create a journal with notes" do
639 should "create a journal with notes" do
644 date = Date.today
640 date = Date.today
645 notes = "Notes added when copying"
641 notes = "Notes added when copying"
646 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :notes => notes, :attributes => {:start_date => date}})
642 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :notes => notes, :attributes => {:start_date => date}})
647
643
648 assert_equal 1, @copy.journals.size
644 assert_equal 1, @copy.journals.size
649 journal = @copy.journals.first
645 journal = @copy.journals.first
650 assert_equal 0, journal.details.size
646 assert_equal 0, journal.details.size
651 assert_equal notes, journal.notes
647 assert_equal notes, journal.notes
652 end
648 end
653 end
649 end
654 end
650 end
655
651
656 def test_recipients_should_not_include_users_that_cannot_view_the_issue
652 def test_recipients_should_not_include_users_that_cannot_view_the_issue
657 issue = Issue.find(12)
653 issue = Issue.find(12)
658 assert issue.recipients.include?(issue.author.mail)
654 assert issue.recipients.include?(issue.author.mail)
659 # move the issue to a private project
655 # move the issue to a private project
660 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
656 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
661 # author is not a member of project anymore
657 # author is not a member of project anymore
662 assert !copy.recipients.include?(copy.author.mail)
658 assert !copy.recipients.include?(copy.author.mail)
663 end
659 end
664
660
665 def test_recipients_should_include_the_assigned_group_members
661 def test_recipients_should_include_the_assigned_group_members
666 group_member = User.generate_with_protected!
662 group_member = User.generate_with_protected!
667 group = Group.generate!
663 group = Group.generate!
668 group.users << group_member
664 group.users << group_member
669
665
670 issue = Issue.find(12)
666 issue = Issue.find(12)
671 issue.assigned_to = group
667 issue.assigned_to = group
672 assert issue.recipients.include?(group_member.mail)
668 assert issue.recipients.include?(group_member.mail)
673 end
669 end
674
670
675 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
671 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
676 user = User.find(3)
672 user = User.find(3)
677 issue = Issue.find(9)
673 issue = Issue.find(9)
678 Watcher.create!(:user => user, :watchable => issue)
674 Watcher.create!(:user => user, :watchable => issue)
679 assert issue.watched_by?(user)
675 assert issue.watched_by?(user)
680 assert !issue.watcher_recipients.include?(user.mail)
676 assert !issue.watcher_recipients.include?(user.mail)
681 end
677 end
682
678
683 def test_issue_destroy
679 def test_issue_destroy
684 Issue.find(1).destroy
680 Issue.find(1).destroy
685 assert_nil Issue.find_by_id(1)
681 assert_nil Issue.find_by_id(1)
686 assert_nil TimeEntry.find_by_issue_id(1)
682 assert_nil TimeEntry.find_by_issue_id(1)
687 end
683 end
688
684
689 def test_blocked
685 def test_blocked
690 blocked_issue = Issue.find(9)
686 blocked_issue = Issue.find(9)
691 blocking_issue = Issue.find(10)
687 blocking_issue = Issue.find(10)
692
688
693 assert blocked_issue.blocked?
689 assert blocked_issue.blocked?
694 assert !blocking_issue.blocked?
690 assert !blocking_issue.blocked?
695 end
691 end
696
692
697 def test_blocked_issues_dont_allow_closed_statuses
693 def test_blocked_issues_dont_allow_closed_statuses
698 blocked_issue = Issue.find(9)
694 blocked_issue = Issue.find(9)
699
695
700 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
696 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
701 assert !allowed_statuses.empty?
697 assert !allowed_statuses.empty?
702 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
698 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
703 assert closed_statuses.empty?
699 assert closed_statuses.empty?
704 end
700 end
705
701
706 def test_unblocked_issues_allow_closed_statuses
702 def test_unblocked_issues_allow_closed_statuses
707 blocking_issue = Issue.find(10)
703 blocking_issue = Issue.find(10)
708
704
709 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
705 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
710 assert !allowed_statuses.empty?
706 assert !allowed_statuses.empty?
711 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
707 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
712 assert !closed_statuses.empty?
708 assert !closed_statuses.empty?
713 end
709 end
714
710
715 def test_rescheduling_an_issue_should_reschedule_following_issue
711 def test_rescheduling_an_issue_should_reschedule_following_issue
716 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
712 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
717 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
713 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
718 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
714 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
719 assert_equal issue1.due_date + 1, issue2.reload.start_date
715 assert_equal issue1.due_date + 1, issue2.reload.start_date
720
716
721 issue1.due_date = Date.today + 5
717 issue1.due_date = Date.today + 5
722 issue1.save!
718 issue1.save!
723 assert_equal issue1.due_date + 1, issue2.reload.start_date
719 assert_equal issue1.due_date + 1, issue2.reload.start_date
724 end
720 end
725
721
726 def test_overdue
722 def test_overdue
727 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
723 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
728 assert !Issue.new(:due_date => Date.today).overdue?
724 assert !Issue.new(:due_date => Date.today).overdue?
729 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
725 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
730 assert !Issue.new(:due_date => nil).overdue?
726 assert !Issue.new(:due_date => nil).overdue?
731 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
727 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
732 end
728 end
733
729
734 context "#behind_schedule?" do
730 context "#behind_schedule?" do
735 should "be false if the issue has no start_date" do
731 should "be false if the issue has no start_date" do
736 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
732 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
737 end
733 end
738
734
739 should "be false if the issue has no end_date" do
735 should "be false if the issue has no end_date" do
740 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
736 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
741 end
737 end
742
738
743 should "be false if the issue has more done than it's calendar time" do
739 should "be false if the issue has more done than it's calendar time" do
744 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
740 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
745 end
741 end
746
742
747 should "be true if the issue hasn't been started at all" do
743 should "be true if the issue hasn't been started at all" do
748 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
744 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
749 end
745 end
750
746
751 should "be true if the issue has used more calendar time than it's done ratio" do
747 should "be true if the issue has used more calendar time than it's done ratio" do
752 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
748 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
753 end
749 end
754 end
750 end
755
751
756 context "#assignable_users" do
752 context "#assignable_users" do
757 should "be Users" do
753 should "be Users" do
758 assert_kind_of User, Issue.find(1).assignable_users.first
754 assert_kind_of User, Issue.find(1).assignable_users.first
759 end
755 end
760
756
761 should "include the issue author" do
757 should "include the issue author" do
762 project = Project.find(1)
758 project = Project.find(1)
763 non_project_member = User.generate!
759 non_project_member = User.generate!
764 issue = Issue.generate_for_project!(project, :author => non_project_member)
760 issue = Issue.generate_for_project!(project, :author => non_project_member)
765
761
766 assert issue.assignable_users.include?(non_project_member)
762 assert issue.assignable_users.include?(non_project_member)
767 end
763 end
768
764
769 should "include the current assignee" do
765 should "include the current assignee" do
770 project = Project.find(1)
766 project = Project.find(1)
771 user = User.generate!
767 user = User.generate!
772 issue = Issue.generate_for_project!(project, :assigned_to => user)
768 issue = Issue.generate_for_project!(project, :assigned_to => user)
773 user.lock!
769 user.lock!
774
770
775 assert Issue.find(issue.id).assignable_users.include?(user)
771 assert Issue.find(issue.id).assignable_users.include?(user)
776 end
772 end
777
773
778 should "not show the issue author twice" do
774 should "not show the issue author twice" do
779 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
775 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
780 assert_equal 2, assignable_user_ids.length
776 assert_equal 2, assignable_user_ids.length
781
777
782 assignable_user_ids.each do |user_id|
778 assignable_user_ids.each do |user_id|
783 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
779 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
784 end
780 end
785 end
781 end
786
782
787 context "with issue_group_assignment" do
783 context "with issue_group_assignment" do
788 should "include groups" do
784 should "include groups" do
789 issue = Issue.new(:project => Project.find(2))
785 issue = Issue.new(:project => Project.find(2))
790
786
791 with_settings :issue_group_assignment => '1' do
787 with_settings :issue_group_assignment => '1' do
792 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
788 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
793 assert issue.assignable_users.include?(Group.find(11))
789 assert issue.assignable_users.include?(Group.find(11))
794 end
790 end
795 end
791 end
796 end
792 end
797
793
798 context "without issue_group_assignment" do
794 context "without issue_group_assignment" do
799 should "not include groups" do
795 should "not include groups" do
800 issue = Issue.new(:project => Project.find(2))
796 issue = Issue.new(:project => Project.find(2))
801
797
802 with_settings :issue_group_assignment => '0' do
798 with_settings :issue_group_assignment => '0' do
803 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
799 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
804 assert !issue.assignable_users.include?(Group.find(11))
800 assert !issue.assignable_users.include?(Group.find(11))
805 end
801 end
806 end
802 end
807 end
803 end
808 end
804 end
809
805
810 def test_create_should_send_email_notification
806 def test_create_should_send_email_notification
811 ActionMailer::Base.deliveries.clear
807 ActionMailer::Base.deliveries.clear
812 issue = Issue.new(:project_id => 1, :tracker_id => 1,
808 issue = Issue.new(:project_id => 1, :tracker_id => 1,
813 :author_id => 3, :status_id => 1,
809 :author_id => 3, :status_id => 1,
814 :priority => IssuePriority.all.first,
810 :priority => IssuePriority.all.first,
815 :subject => 'test_create', :estimated_hours => '1:30')
811 :subject => 'test_create', :estimated_hours => '1:30')
816
812
817 assert issue.save
813 assert issue.save
818 assert_equal 1, ActionMailer::Base.deliveries.size
814 assert_equal 1, ActionMailer::Base.deliveries.size
819 end
815 end
820
816
821 def test_stale_issue_should_not_send_email_notification
817 def test_stale_issue_should_not_send_email_notification
822 ActionMailer::Base.deliveries.clear
818 ActionMailer::Base.deliveries.clear
823 issue = Issue.find(1)
819 issue = Issue.find(1)
824 stale = Issue.find(1)
820 stale = Issue.find(1)
825
821
826 issue.init_journal(User.find(1))
822 issue.init_journal(User.find(1))
827 issue.subject = 'Subjet update'
823 issue.subject = 'Subjet update'
828 assert issue.save
824 assert issue.save
829 assert_equal 1, ActionMailer::Base.deliveries.size
825 assert_equal 1, ActionMailer::Base.deliveries.size
830 ActionMailer::Base.deliveries.clear
826 ActionMailer::Base.deliveries.clear
831
827
832 stale.init_journal(User.find(1))
828 stale.init_journal(User.find(1))
833 stale.subject = 'Another subjet update'
829 stale.subject = 'Another subjet update'
834 assert_raise ActiveRecord::StaleObjectError do
830 assert_raise ActiveRecord::StaleObjectError do
835 stale.save
831 stale.save
836 end
832 end
837 assert ActionMailer::Base.deliveries.empty?
833 assert ActionMailer::Base.deliveries.empty?
838 end
834 end
839
835
840 def test_journalized_description
836 def test_journalized_description
841 IssueCustomField.delete_all
837 IssueCustomField.delete_all
842
838
843 i = Issue.first
839 i = Issue.first
844 old_description = i.description
840 old_description = i.description
845 new_description = "This is the new description"
841 new_description = "This is the new description"
846
842
847 i.init_journal(User.find(2))
843 i.init_journal(User.find(2))
848 i.description = new_description
844 i.description = new_description
849 assert_difference 'Journal.count', 1 do
845 assert_difference 'Journal.count', 1 do
850 assert_difference 'JournalDetail.count', 1 do
846 assert_difference 'JournalDetail.count', 1 do
851 i.save!
847 i.save!
852 end
848 end
853 end
849 end
854
850
855 detail = JournalDetail.first(:order => 'id DESC')
851 detail = JournalDetail.first(:order => 'id DESC')
856 assert_equal i, detail.journal.journalized
852 assert_equal i, detail.journal.journalized
857 assert_equal 'attr', detail.property
853 assert_equal 'attr', detail.property
858 assert_equal 'description', detail.prop_key
854 assert_equal 'description', detail.prop_key
859 assert_equal old_description, detail.old_value
855 assert_equal old_description, detail.old_value
860 assert_equal new_description, detail.value
856 assert_equal new_description, detail.value
861 end
857 end
862
858
863 def test_blank_descriptions_should_not_be_journalized
859 def test_blank_descriptions_should_not_be_journalized
864 IssueCustomField.delete_all
860 IssueCustomField.delete_all
865 Issue.update_all("description = NULL", "id=1")
861 Issue.update_all("description = NULL", "id=1")
866
862
867 i = Issue.find(1)
863 i = Issue.find(1)
868 i.init_journal(User.find(2))
864 i.init_journal(User.find(2))
869 i.subject = "blank description"
865 i.subject = "blank description"
870 i.description = "\r\n"
866 i.description = "\r\n"
871
867
872 assert_difference 'Journal.count', 1 do
868 assert_difference 'Journal.count', 1 do
873 assert_difference 'JournalDetail.count', 1 do
869 assert_difference 'JournalDetail.count', 1 do
874 i.save!
870 i.save!
875 end
871 end
876 end
872 end
877 end
873 end
878
874
879 def test_description_eol_should_be_normalized
875 def test_description_eol_should_be_normalized
880 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
876 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
881 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
877 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
882 end
878 end
883
879
884 def test_saving_twice_should_not_duplicate_journal_details
880 def test_saving_twice_should_not_duplicate_journal_details
885 i = Issue.find(:first)
881 i = Issue.find(:first)
886 i.init_journal(User.find(2), 'Some notes')
882 i.init_journal(User.find(2), 'Some notes')
887 # initial changes
883 # initial changes
888 i.subject = 'New subject'
884 i.subject = 'New subject'
889 i.done_ratio = i.done_ratio + 10
885 i.done_ratio = i.done_ratio + 10
890 assert_difference 'Journal.count' do
886 assert_difference 'Journal.count' do
891 assert i.save
887 assert i.save
892 end
888 end
893 # 1 more change
889 # 1 more change
894 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
890 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
895 assert_no_difference 'Journal.count' do
891 assert_no_difference 'Journal.count' do
896 assert_difference 'JournalDetail.count', 1 do
892 assert_difference 'JournalDetail.count', 1 do
897 i.save
893 i.save
898 end
894 end
899 end
895 end
900 # no more change
896 # no more change
901 assert_no_difference 'Journal.count' do
897 assert_no_difference 'Journal.count' do
902 assert_no_difference 'JournalDetail.count' do
898 assert_no_difference 'JournalDetail.count' do
903 i.save
899 i.save
904 end
900 end
905 end
901 end
906 end
902 end
907
903
908 def test_all_dependent_issues
904 def test_all_dependent_issues
909 IssueRelation.delete_all
905 IssueRelation.delete_all
910 assert IssueRelation.create!(:issue_from => Issue.find(1),
906 assert IssueRelation.create!(:issue_from => Issue.find(1),
911 :issue_to => Issue.find(2),
907 :issue_to => Issue.find(2),
912 :relation_type => IssueRelation::TYPE_PRECEDES)
908 :relation_type => IssueRelation::TYPE_PRECEDES)
913 assert IssueRelation.create!(:issue_from => Issue.find(2),
909 assert IssueRelation.create!(:issue_from => Issue.find(2),
914 :issue_to => Issue.find(3),
910 :issue_to => Issue.find(3),
915 :relation_type => IssueRelation::TYPE_PRECEDES)
911 :relation_type => IssueRelation::TYPE_PRECEDES)
916 assert IssueRelation.create!(:issue_from => Issue.find(3),
912 assert IssueRelation.create!(:issue_from => Issue.find(3),
917 :issue_to => Issue.find(8),
913 :issue_to => Issue.find(8),
918 :relation_type => IssueRelation::TYPE_PRECEDES)
914 :relation_type => IssueRelation::TYPE_PRECEDES)
919
915
920 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
916 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
921 end
917 end
922
918
923 def test_all_dependent_issues_with_persistent_circular_dependency
919 def test_all_dependent_issues_with_persistent_circular_dependency
924 IssueRelation.delete_all
920 IssueRelation.delete_all
925 assert IssueRelation.create!(:issue_from => Issue.find(1),
921 assert IssueRelation.create!(:issue_from => Issue.find(1),
926 :issue_to => Issue.find(2),
922 :issue_to => Issue.find(2),
927 :relation_type => IssueRelation::TYPE_PRECEDES)
923 :relation_type => IssueRelation::TYPE_PRECEDES)
928 assert IssueRelation.create!(:issue_from => Issue.find(2),
924 assert IssueRelation.create!(:issue_from => Issue.find(2),
929 :issue_to => Issue.find(3),
925 :issue_to => Issue.find(3),
930 :relation_type => IssueRelation::TYPE_PRECEDES)
926 :relation_type => IssueRelation::TYPE_PRECEDES)
931 # Validation skipping
927 # Validation skipping
932 assert IssueRelation.new(:issue_from => Issue.find(3),
928 assert IssueRelation.new(:issue_from => Issue.find(3),
933 :issue_to => Issue.find(1),
929 :issue_to => Issue.find(1),
934 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
930 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
935
931
936 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
932 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
937 end
933 end
938
934
939 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
935 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
940 IssueRelation.delete_all
936 IssueRelation.delete_all
941 assert IssueRelation.create!(:issue_from => Issue.find(1),
937 assert IssueRelation.create!(:issue_from => Issue.find(1),
942 :issue_to => Issue.find(2),
938 :issue_to => Issue.find(2),
943 :relation_type => IssueRelation::TYPE_RELATES)
939 :relation_type => IssueRelation::TYPE_RELATES)
944 assert IssueRelation.create!(:issue_from => Issue.find(2),
940 assert IssueRelation.create!(:issue_from => Issue.find(2),
945 :issue_to => Issue.find(3),
941 :issue_to => Issue.find(3),
946 :relation_type => IssueRelation::TYPE_RELATES)
942 :relation_type => IssueRelation::TYPE_RELATES)
947 assert IssueRelation.create!(:issue_from => Issue.find(3),
943 assert IssueRelation.create!(:issue_from => Issue.find(3),
948 :issue_to => Issue.find(8),
944 :issue_to => Issue.find(8),
949 :relation_type => IssueRelation::TYPE_RELATES)
945 :relation_type => IssueRelation::TYPE_RELATES)
950 # Validation skipping
946 # Validation skipping
951 assert IssueRelation.new(:issue_from => Issue.find(8),
947 assert IssueRelation.new(:issue_from => Issue.find(8),
952 :issue_to => Issue.find(2),
948 :issue_to => Issue.find(2),
953 :relation_type => IssueRelation::TYPE_RELATES).save(false)
949 :relation_type => IssueRelation::TYPE_RELATES).save(false)
954 assert IssueRelation.new(:issue_from => Issue.find(3),
950 assert IssueRelation.new(:issue_from => Issue.find(3),
955 :issue_to => Issue.find(1),
951 :issue_to => Issue.find(1),
956 :relation_type => IssueRelation::TYPE_RELATES).save(false)
952 :relation_type => IssueRelation::TYPE_RELATES).save(false)
957
953
958 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
954 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
959 end
955 end
960
956
961 context "#done_ratio" do
957 context "#done_ratio" do
962 setup do
958 setup do
963 @issue = Issue.find(1)
959 @issue = Issue.find(1)
964 @issue_status = IssueStatus.find(1)
960 @issue_status = IssueStatus.find(1)
965 @issue_status.update_attribute(:default_done_ratio, 50)
961 @issue_status.update_attribute(:default_done_ratio, 50)
966 @issue2 = Issue.find(2)
962 @issue2 = Issue.find(2)
967 @issue_status2 = IssueStatus.find(2)
963 @issue_status2 = IssueStatus.find(2)
968 @issue_status2.update_attribute(:default_done_ratio, 0)
964 @issue_status2.update_attribute(:default_done_ratio, 0)
969 end
965 end
970
966
971 teardown do
967 teardown do
972 Setting.issue_done_ratio = 'issue_field'
968 Setting.issue_done_ratio = 'issue_field'
973 end
969 end
974
970
975 context "with Setting.issue_done_ratio using the issue_field" do
971 context "with Setting.issue_done_ratio using the issue_field" do
976 setup do
972 setup do
977 Setting.issue_done_ratio = 'issue_field'
973 Setting.issue_done_ratio = 'issue_field'
978 end
974 end
979
975
980 should "read the issue's field" do
976 should "read the issue's field" do
981 assert_equal 0, @issue.done_ratio
977 assert_equal 0, @issue.done_ratio
982 assert_equal 30, @issue2.done_ratio
978 assert_equal 30, @issue2.done_ratio
983 end
979 end
984 end
980 end
985
981
986 context "with Setting.issue_done_ratio using the issue_status" do
982 context "with Setting.issue_done_ratio using the issue_status" do
987 setup do
983 setup do
988 Setting.issue_done_ratio = 'issue_status'
984 Setting.issue_done_ratio = 'issue_status'
989 end
985 end
990
986
991 should "read the Issue Status's default done ratio" do
987 should "read the Issue Status's default done ratio" do
992 assert_equal 50, @issue.done_ratio
988 assert_equal 50, @issue.done_ratio
993 assert_equal 0, @issue2.done_ratio
989 assert_equal 0, @issue2.done_ratio
994 end
990 end
995 end
991 end
996 end
992 end
997
993
998 context "#update_done_ratio_from_issue_status" do
994 context "#update_done_ratio_from_issue_status" do
999 setup do
995 setup do
1000 @issue = Issue.find(1)
996 @issue = Issue.find(1)
1001 @issue_status = IssueStatus.find(1)
997 @issue_status = IssueStatus.find(1)
1002 @issue_status.update_attribute(:default_done_ratio, 50)
998 @issue_status.update_attribute(:default_done_ratio, 50)
1003 @issue2 = Issue.find(2)
999 @issue2 = Issue.find(2)
1004 @issue_status2 = IssueStatus.find(2)
1000 @issue_status2 = IssueStatus.find(2)
1005 @issue_status2.update_attribute(:default_done_ratio, 0)
1001 @issue_status2.update_attribute(:default_done_ratio, 0)
1006 end
1002 end
1007
1003
1008 context "with Setting.issue_done_ratio using the issue_field" do
1004 context "with Setting.issue_done_ratio using the issue_field" do
1009 setup do
1005 setup do
1010 Setting.issue_done_ratio = 'issue_field'
1006 Setting.issue_done_ratio = 'issue_field'
1011 end
1007 end
1012
1008
1013 should "not change the issue" do
1009 should "not change the issue" do
1014 @issue.update_done_ratio_from_issue_status
1010 @issue.update_done_ratio_from_issue_status
1015 @issue2.update_done_ratio_from_issue_status
1011 @issue2.update_done_ratio_from_issue_status
1016
1012
1017 assert_equal 0, @issue.read_attribute(:done_ratio)
1013 assert_equal 0, @issue.read_attribute(:done_ratio)
1018 assert_equal 30, @issue2.read_attribute(:done_ratio)
1014 assert_equal 30, @issue2.read_attribute(:done_ratio)
1019 end
1015 end
1020 end
1016 end
1021
1017
1022 context "with Setting.issue_done_ratio using the issue_status" do
1018 context "with Setting.issue_done_ratio using the issue_status" do
1023 setup do
1019 setup do
1024 Setting.issue_done_ratio = 'issue_status'
1020 Setting.issue_done_ratio = 'issue_status'
1025 end
1021 end
1026
1022
1027 should "change the issue's done ratio" do
1023 should "change the issue's done ratio" do
1028 @issue.update_done_ratio_from_issue_status
1024 @issue.update_done_ratio_from_issue_status
1029 @issue2.update_done_ratio_from_issue_status
1025 @issue2.update_done_ratio_from_issue_status
1030
1026
1031 assert_equal 50, @issue.read_attribute(:done_ratio)
1027 assert_equal 50, @issue.read_attribute(:done_ratio)
1032 assert_equal 0, @issue2.read_attribute(:done_ratio)
1028 assert_equal 0, @issue2.read_attribute(:done_ratio)
1033 end
1029 end
1034 end
1030 end
1035 end
1031 end
1036
1032
1037 test "#by_tracker" do
1033 test "#by_tracker" do
1038 User.current = User.anonymous
1034 User.current = User.anonymous
1039 groups = Issue.by_tracker(Project.find(1))
1035 groups = Issue.by_tracker(Project.find(1))
1040 assert_equal 3, groups.size
1036 assert_equal 3, groups.size
1041 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1037 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1042 end
1038 end
1043
1039
1044 test "#by_version" do
1040 test "#by_version" do
1045 User.current = User.anonymous
1041 User.current = User.anonymous
1046 groups = Issue.by_version(Project.find(1))
1042 groups = Issue.by_version(Project.find(1))
1047 assert_equal 3, groups.size
1043 assert_equal 3, groups.size
1048 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1044 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1049 end
1045 end
1050
1046
1051 test "#by_priority" do
1047 test "#by_priority" do
1052 User.current = User.anonymous
1048 User.current = User.anonymous
1053 groups = Issue.by_priority(Project.find(1))
1049 groups = Issue.by_priority(Project.find(1))
1054 assert_equal 4, groups.size
1050 assert_equal 4, groups.size
1055 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1051 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1056 end
1052 end
1057
1053
1058 test "#by_category" do
1054 test "#by_category" do
1059 User.current = User.anonymous
1055 User.current = User.anonymous
1060 groups = Issue.by_category(Project.find(1))
1056 groups = Issue.by_category(Project.find(1))
1061 assert_equal 2, groups.size
1057 assert_equal 2, groups.size
1062 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1058 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1063 end
1059 end
1064
1060
1065 test "#by_assigned_to" do
1061 test "#by_assigned_to" do
1066 User.current = User.anonymous
1062 User.current = User.anonymous
1067 groups = Issue.by_assigned_to(Project.find(1))
1063 groups = Issue.by_assigned_to(Project.find(1))
1068 assert_equal 2, groups.size
1064 assert_equal 2, groups.size
1069 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1065 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1070 end
1066 end
1071
1067
1072 test "#by_author" do
1068 test "#by_author" do
1073 User.current = User.anonymous
1069 User.current = User.anonymous
1074 groups = Issue.by_author(Project.find(1))
1070 groups = Issue.by_author(Project.find(1))
1075 assert_equal 4, groups.size
1071 assert_equal 4, groups.size
1076 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1072 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1077 end
1073 end
1078
1074
1079 test "#by_subproject" do
1075 test "#by_subproject" do
1080 User.current = User.anonymous
1076 User.current = User.anonymous
1081 groups = Issue.by_subproject(Project.find(1))
1077 groups = Issue.by_subproject(Project.find(1))
1082 # Private descendant not visible
1078 # Private descendant not visible
1083 assert_equal 1, groups.size
1079 assert_equal 1, groups.size
1084 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1080 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1085 end
1081 end
1086
1082
1087 context ".allowed_target_projects_on_move" do
1083 context ".allowed_target_projects_on_move" do
1088 should "return all active projects for admin users" do
1084 should "return all active projects for admin users" do
1089 User.current = User.find(1)
1085 User.current = User.find(1)
1090 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1086 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1091 end
1087 end
1092
1088
1093 should "return allowed projects for non admin users" do
1089 should "return allowed projects for non admin users" do
1094 User.current = User.find(2)
1090 User.current = User.find(2)
1095 Role.non_member.remove_permission! :move_issues
1091 Role.non_member.remove_permission! :move_issues
1096 assert_equal 3, Issue.allowed_target_projects_on_move.size
1092 assert_equal 3, Issue.allowed_target_projects_on_move.size
1097
1093
1098 Role.non_member.add_permission! :move_issues
1094 Role.non_member.add_permission! :move_issues
1099 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1095 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1100 end
1096 end
1101 end
1097 end
1102
1098
1103 def test_recently_updated_with_limit_scopes
1099 def test_recently_updated_with_limit_scopes
1104 #should return the last updated issue
1100 #should return the last updated issue
1105 assert_equal 1, Issue.recently_updated.with_limit(1).length
1101 assert_equal 1, Issue.recently_updated.with_limit(1).length
1106 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1102 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1107 end
1103 end
1108
1104
1109 def test_on_active_projects_scope
1105 def test_on_active_projects_scope
1110 assert Project.find(2).archive
1106 assert Project.find(2).archive
1111
1107
1112 before = Issue.on_active_project.length
1108 before = Issue.on_active_project.length
1113 # test inclusion to results
1109 # test inclusion to results
1114 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1110 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1115 assert_equal before + 1, Issue.on_active_project.length
1111 assert_equal before + 1, Issue.on_active_project.length
1116
1112
1117 # Move to an archived project
1113 # Move to an archived project
1118 issue.project = Project.find(2)
1114 issue.project = Project.find(2)
1119 assert issue.save
1115 assert issue.save
1120 assert_equal before, Issue.on_active_project.length
1116 assert_equal before, Issue.on_active_project.length
1121 end
1117 end
1122
1118
1123 context "Issue#recipients" do
1119 context "Issue#recipients" do
1124 setup do
1120 setup do
1125 @project = Project.find(1)
1121 @project = Project.find(1)
1126 @author = User.generate_with_protected!
1122 @author = User.generate_with_protected!
1127 @assignee = User.generate_with_protected!
1123 @assignee = User.generate_with_protected!
1128 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1124 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1129 end
1125 end
1130
1126
1131 should "include project recipients" do
1127 should "include project recipients" do
1132 assert @project.recipients.present?
1128 assert @project.recipients.present?
1133 @project.recipients.each do |project_recipient|
1129 @project.recipients.each do |project_recipient|
1134 assert @issue.recipients.include?(project_recipient)
1130 assert @issue.recipients.include?(project_recipient)
1135 end
1131 end
1136 end
1132 end
1137
1133
1138 should "include the author if the author is active" do
1134 should "include the author if the author is active" do
1139 assert @issue.author, "No author set for Issue"
1135 assert @issue.author, "No author set for Issue"
1140 assert @issue.recipients.include?(@issue.author.mail)
1136 assert @issue.recipients.include?(@issue.author.mail)
1141 end
1137 end
1142
1138
1143 should "include the assigned to user if the assigned to user is active" do
1139 should "include the assigned to user if the assigned to user is active" do
1144 assert @issue.assigned_to, "No assigned_to set for Issue"
1140 assert @issue.assigned_to, "No assigned_to set for Issue"
1145 assert @issue.recipients.include?(@issue.assigned_to.mail)
1141 assert @issue.recipients.include?(@issue.assigned_to.mail)
1146 end
1142 end
1147
1143
1148 should "not include users who opt out of all email" do
1144 should "not include users who opt out of all email" do
1149 @author.update_attribute(:mail_notification, :none)
1145 @author.update_attribute(:mail_notification, :none)
1150
1146
1151 assert !@issue.recipients.include?(@issue.author.mail)
1147 assert !@issue.recipients.include?(@issue.author.mail)
1152 end
1148 end
1153
1149
1154 should "not include the issue author if they are only notified of assigned issues" do
1150 should "not include the issue author if they are only notified of assigned issues" do
1155 @author.update_attribute(:mail_notification, :only_assigned)
1151 @author.update_attribute(:mail_notification, :only_assigned)
1156
1152
1157 assert !@issue.recipients.include?(@issue.author.mail)
1153 assert !@issue.recipients.include?(@issue.author.mail)
1158 end
1154 end
1159
1155
1160 should "not include the assigned user if they are only notified of owned issues" do
1156 should "not include the assigned user if they are only notified of owned issues" do
1161 @assignee.update_attribute(:mail_notification, :only_owner)
1157 @assignee.update_attribute(:mail_notification, :only_owner)
1162
1158
1163 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1159 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1164 end
1160 end
1165
1161
1166 end
1162 end
1167 end
1163 end
General Comments 0
You need to be logged in to leave comments. Login now