##// END OF EJS Templates
Use fixtures generator....
Jean-Philippe Lang -
r8174:aec1828fc763
parent child
Show More
@@ -1,1171 +1,1167
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 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
411 project = Project.find(1)
412 :status_id => 1, :priority => IssuePriority.all.first,
412 issue1 = Issue.generate_for_project!(project)
413 :subject => 'Duplicates test', :description => 'Duplicates test')
413 issue2 = Issue.generate_for_project!(project)
414 assert issue1.save
414 issue3 = Issue.generate_for_project!(project)
415 issue2 = issue1.clone
416 assert issue2.save
417 issue3 = issue1.clone
418 assert issue3.save
419
415
420 # 2 is a dupe of 1
416 # 2 is a dupe of 1
421 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)
422 # And 3 is a dupe of 2
418 # And 3 is a dupe of 2
423 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)
424 # And 3 is a dupe of 1 (circular duplicates)
420 # And 3 is a dupe of 1 (circular duplicates)
425 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)
426
422
427 assert issue1.reload.duplicates.include?(issue2)
423 assert issue1.reload.duplicates.include?(issue2)
428
424
429 # Closing issue 1
425 # Closing issue 1
430 issue1.init_journal(User.find(:first), "Closing issue1")
426 issue1.init_journal(User.find(:first), "Closing issue1")
431 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
427 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
432 assert issue1.save
428 assert issue1.save
433 # 2 and 3 should be also closed
429 # 2 and 3 should be also closed
434 assert issue2.reload.closed?
430 assert issue2.reload.closed?
435 assert issue3.reload.closed?
431 assert issue3.reload.closed?
436 end
432 end
437
433
438 def test_should_not_close_duplicated_issue
434 def test_should_not_close_duplicated_issue
439 # Create 3 issues
435 # Create 3 issues
440 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
436 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
441 :status_id => 1, :priority => IssuePriority.all.first,
437 :status_id => 1, :priority => IssuePriority.all.first,
442 :subject => 'Duplicates test', :description => 'Duplicates test')
438 :subject => 'Duplicates test', :description => 'Duplicates test')
443 assert issue1.save
439 assert issue1.save
444 issue2 = issue1.clone
440 issue2 = issue1.clone
445 assert issue2.save
441 assert issue2.save
446
442
447 # 2 is a dupe of 1
443 # 2 is a dupe of 1
448 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
444 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
449 # 2 is a dup of 1 but 1 is not a duplicate of 2
445 # 2 is a dup of 1 but 1 is not a duplicate of 2
450 assert !issue2.reload.duplicates.include?(issue1)
446 assert !issue2.reload.duplicates.include?(issue1)
451
447
452 # Closing issue 2
448 # Closing issue 2
453 issue2.init_journal(User.find(:first), "Closing issue2")
449 issue2.init_journal(User.find(:first), "Closing issue2")
454 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
450 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
455 assert issue2.save
451 assert issue2.save
456 # 1 should not be also closed
452 # 1 should not be also closed
457 assert !issue1.reload.closed?
453 assert !issue1.reload.closed?
458 end
454 end
459
455
460 def test_assignable_versions
456 def test_assignable_versions
461 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
457 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
462 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
458 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
463 end
459 end
464
460
465 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
461 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
466 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
462 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
467 assert !issue.save
463 assert !issue.save
468 assert_not_nil issue.errors[:fixed_version_id]
464 assert_not_nil issue.errors[:fixed_version_id]
469 end
465 end
470
466
471 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
467 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
472 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
468 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
473 assert !issue.save
469 assert !issue.save
474 assert_not_nil issue.errors[:fixed_version_id]
470 assert_not_nil issue.errors[:fixed_version_id]
475 end
471 end
476
472
477 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
473 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
478 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
474 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
479 assert issue.save
475 assert issue.save
480 end
476 end
481
477
482 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
478 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
483 issue = Issue.find(11)
479 issue = Issue.find(11)
484 assert_equal 'closed', issue.fixed_version.status
480 assert_equal 'closed', issue.fixed_version.status
485 issue.subject = 'Subject changed'
481 issue.subject = 'Subject changed'
486 assert issue.save
482 assert issue.save
487 end
483 end
488
484
489 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
485 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
490 issue = Issue.find(11)
486 issue = Issue.find(11)
491 issue.status_id = 1
487 issue.status_id = 1
492 assert !issue.save
488 assert !issue.save
493 assert_not_nil issue.errors[:base]
489 assert_not_nil issue.errors[:base]
494 end
490 end
495
491
496 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
492 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
497 issue = Issue.find(11)
493 issue = Issue.find(11)
498 issue.status_id = 1
494 issue.status_id = 1
499 issue.fixed_version_id = 3
495 issue.fixed_version_id = 3
500 assert issue.save
496 assert issue.save
501 end
497 end
502
498
503 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
499 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
504 issue = Issue.find(12)
500 issue = Issue.find(12)
505 assert_equal 'locked', issue.fixed_version.status
501 assert_equal 'locked', issue.fixed_version.status
506 issue.status_id = 1
502 issue.status_id = 1
507 assert issue.save
503 assert issue.save
508 end
504 end
509
505
510 def test_move_to_another_project_with_same_category
506 def test_move_to_another_project_with_same_category
511 issue = Issue.find(1)
507 issue = Issue.find(1)
512 assert issue.move_to_project(Project.find(2))
508 assert issue.move_to_project(Project.find(2))
513 issue.reload
509 issue.reload
514 assert_equal 2, issue.project_id
510 assert_equal 2, issue.project_id
515 # Category changes
511 # Category changes
516 assert_equal 4, issue.category_id
512 assert_equal 4, issue.category_id
517 # Make sure time entries were move to the target project
513 # Make sure time entries were move to the target project
518 assert_equal 2, issue.time_entries.first.project_id
514 assert_equal 2, issue.time_entries.first.project_id
519 end
515 end
520
516
521 def test_move_to_another_project_without_same_category
517 def test_move_to_another_project_without_same_category
522 issue = Issue.find(2)
518 issue = Issue.find(2)
523 assert issue.move_to_project(Project.find(2))
519 assert issue.move_to_project(Project.find(2))
524 issue.reload
520 issue.reload
525 assert_equal 2, issue.project_id
521 assert_equal 2, issue.project_id
526 # Category cleared
522 # Category cleared
527 assert_nil issue.category_id
523 assert_nil issue.category_id
528 end
524 end
529
525
530 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
526 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
531 issue = Issue.find(1)
527 issue = Issue.find(1)
532 issue.update_attribute(:fixed_version_id, 1)
528 issue.update_attribute(:fixed_version_id, 1)
533 assert issue.move_to_project(Project.find(2))
529 assert issue.move_to_project(Project.find(2))
534 issue.reload
530 issue.reload
535 assert_equal 2, issue.project_id
531 assert_equal 2, issue.project_id
536 # Cleared fixed_version
532 # Cleared fixed_version
537 assert_equal nil, issue.fixed_version
533 assert_equal nil, issue.fixed_version
538 end
534 end
539
535
540 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
536 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
541 issue = Issue.find(1)
537 issue = Issue.find(1)
542 issue.update_attribute(:fixed_version_id, 4)
538 issue.update_attribute(:fixed_version_id, 4)
543 assert issue.move_to_project(Project.find(5))
539 assert issue.move_to_project(Project.find(5))
544 issue.reload
540 issue.reload
545 assert_equal 5, issue.project_id
541 assert_equal 5, issue.project_id
546 # Keep fixed_version
542 # Keep fixed_version
547 assert_equal 4, issue.fixed_version_id
543 assert_equal 4, issue.fixed_version_id
548 end
544 end
549
545
550 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
546 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
551 issue = Issue.find(1)
547 issue = Issue.find(1)
552 issue.update_attribute(:fixed_version_id, 1)
548 issue.update_attribute(:fixed_version_id, 1)
553 assert issue.move_to_project(Project.find(5))
549 assert issue.move_to_project(Project.find(5))
554 issue.reload
550 issue.reload
555 assert_equal 5, issue.project_id
551 assert_equal 5, issue.project_id
556 # Cleared fixed_version
552 # Cleared fixed_version
557 assert_equal nil, issue.fixed_version
553 assert_equal nil, issue.fixed_version
558 end
554 end
559
555
560 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
556 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
561 issue = Issue.find(1)
557 issue = Issue.find(1)
562 issue.update_attribute(:fixed_version_id, 7)
558 issue.update_attribute(:fixed_version_id, 7)
563 assert issue.move_to_project(Project.find(2))
559 assert issue.move_to_project(Project.find(2))
564 issue.reload
560 issue.reload
565 assert_equal 2, issue.project_id
561 assert_equal 2, issue.project_id
566 # Keep fixed_version
562 # Keep fixed_version
567 assert_equal 7, issue.fixed_version_id
563 assert_equal 7, issue.fixed_version_id
568 end
564 end
569
565
570 def test_move_to_another_project_with_disabled_tracker
566 def test_move_to_another_project_with_disabled_tracker
571 issue = Issue.find(1)
567 issue = Issue.find(1)
572 target = Project.find(2)
568 target = Project.find(2)
573 target.tracker_ids = [3]
569 target.tracker_ids = [3]
574 target.save
570 target.save
575 assert_equal false, issue.move_to_project(target)
571 assert_equal false, issue.move_to_project(target)
576 issue.reload
572 issue.reload
577 assert_equal 1, issue.project_id
573 assert_equal 1, issue.project_id
578 end
574 end
579
575
580 def test_copy_to_the_same_project
576 def test_copy_to_the_same_project
581 issue = Issue.find(1)
577 issue = Issue.find(1)
582 copy = nil
578 copy = nil
583 assert_difference 'Issue.count' do
579 assert_difference 'Issue.count' do
584 copy = issue.move_to_project(issue.project, nil, :copy => true)
580 copy = issue.move_to_project(issue.project, nil, :copy => true)
585 end
581 end
586 assert_kind_of Issue, copy
582 assert_kind_of Issue, copy
587 assert_equal issue.project, copy.project
583 assert_equal issue.project, copy.project
588 assert_equal "125", copy.custom_value_for(2).value
584 assert_equal "125", copy.custom_value_for(2).value
589 end
585 end
590
586
591 def test_copy_to_another_project_and_tracker
587 def test_copy_to_another_project_and_tracker
592 issue = Issue.find(1)
588 issue = Issue.find(1)
593 copy = nil
589 copy = nil
594 assert_difference 'Issue.count' do
590 assert_difference 'Issue.count' do
595 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
591 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
596 end
592 end
597 copy.reload
593 copy.reload
598 assert_kind_of Issue, copy
594 assert_kind_of Issue, copy
599 assert_equal Project.find(3), copy.project
595 assert_equal Project.find(3), copy.project
600 assert_equal Tracker.find(2), copy.tracker
596 assert_equal Tracker.find(2), copy.tracker
601 # Custom field #2 is not associated with target tracker
597 # Custom field #2 is not associated with target tracker
602 assert_nil copy.custom_value_for(2)
598 assert_nil copy.custom_value_for(2)
603 end
599 end
604
600
605 context "#move_to_project" do
601 context "#move_to_project" do
606 context "as a copy" do
602 context "as a copy" do
607 setup do
603 setup do
608 @issue = Issue.find(1)
604 @issue = Issue.find(1)
609 @copy = nil
605 @copy = nil
610 end
606 end
611
607
612 should "not create a journal" do
608 should "not create a journal" do
613 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
609 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
614 assert_equal 0, @copy.reload.journals.size
610 assert_equal 0, @copy.reload.journals.size
615 end
611 end
616
612
617 should "allow assigned_to changes" do
613 should "allow assigned_to changes" do
618 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
614 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
619 assert_equal 3, @copy.assigned_to_id
615 assert_equal 3, @copy.assigned_to_id
620 end
616 end
621
617
622 should "allow status changes" do
618 should "allow status changes" do
623 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
619 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
624 assert_equal 2, @copy.status_id
620 assert_equal 2, @copy.status_id
625 end
621 end
626
622
627 should "allow start date changes" do
623 should "allow start date changes" do
628 date = Date.today
624 date = Date.today
629 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
625 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
630 assert_equal date, @copy.start_date
626 assert_equal date, @copy.start_date
631 end
627 end
632
628
633 should "allow due date changes" do
629 should "allow due date changes" do
634 date = Date.today
630 date = Date.today
635 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
631 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
636
632
637 assert_equal date, @copy.due_date
633 assert_equal date, @copy.due_date
638 end
634 end
639
635
640 should "set current user as author" do
636 should "set current user as author" do
641 User.current = User.find(9)
637 User.current = User.find(9)
642 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
638 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
643
639
644 assert_equal User.current, @copy.author
640 assert_equal User.current, @copy.author
645 end
641 end
646
642
647 should "create a journal with notes" do
643 should "create a journal with notes" do
648 date = Date.today
644 date = Date.today
649 notes = "Notes added when copying"
645 notes = "Notes added when copying"
650 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :notes => notes, :attributes => {:start_date => date}})
646 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :notes => notes, :attributes => {:start_date => date}})
651
647
652 assert_equal 1, @copy.journals.size
648 assert_equal 1, @copy.journals.size
653 journal = @copy.journals.first
649 journal = @copy.journals.first
654 assert_equal 0, journal.details.size
650 assert_equal 0, journal.details.size
655 assert_equal notes, journal.notes
651 assert_equal notes, journal.notes
656 end
652 end
657 end
653 end
658 end
654 end
659
655
660 def test_recipients_should_not_include_users_that_cannot_view_the_issue
656 def test_recipients_should_not_include_users_that_cannot_view_the_issue
661 issue = Issue.find(12)
657 issue = Issue.find(12)
662 assert issue.recipients.include?(issue.author.mail)
658 assert issue.recipients.include?(issue.author.mail)
663 # move the issue to a private project
659 # move the issue to a private project
664 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
660 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
665 # author is not a member of project anymore
661 # author is not a member of project anymore
666 assert !copy.recipients.include?(copy.author.mail)
662 assert !copy.recipients.include?(copy.author.mail)
667 end
663 end
668
664
669 def test_recipients_should_include_the_assigned_group_members
665 def test_recipients_should_include_the_assigned_group_members
670 group_member = User.generate_with_protected!
666 group_member = User.generate_with_protected!
671 group = Group.generate!
667 group = Group.generate!
672 group.users << group_member
668 group.users << group_member
673
669
674 issue = Issue.find(12)
670 issue = Issue.find(12)
675 issue.assigned_to = group
671 issue.assigned_to = group
676 assert issue.recipients.include?(group_member.mail)
672 assert issue.recipients.include?(group_member.mail)
677 end
673 end
678
674
679 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
675 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
680 user = User.find(3)
676 user = User.find(3)
681 issue = Issue.find(9)
677 issue = Issue.find(9)
682 Watcher.create!(:user => user, :watchable => issue)
678 Watcher.create!(:user => user, :watchable => issue)
683 assert issue.watched_by?(user)
679 assert issue.watched_by?(user)
684 assert !issue.watcher_recipients.include?(user.mail)
680 assert !issue.watcher_recipients.include?(user.mail)
685 end
681 end
686
682
687 def test_issue_destroy
683 def test_issue_destroy
688 Issue.find(1).destroy
684 Issue.find(1).destroy
689 assert_nil Issue.find_by_id(1)
685 assert_nil Issue.find_by_id(1)
690 assert_nil TimeEntry.find_by_issue_id(1)
686 assert_nil TimeEntry.find_by_issue_id(1)
691 end
687 end
692
688
693 def test_blocked
689 def test_blocked
694 blocked_issue = Issue.find(9)
690 blocked_issue = Issue.find(9)
695 blocking_issue = Issue.find(10)
691 blocking_issue = Issue.find(10)
696
692
697 assert blocked_issue.blocked?
693 assert blocked_issue.blocked?
698 assert !blocking_issue.blocked?
694 assert !blocking_issue.blocked?
699 end
695 end
700
696
701 def test_blocked_issues_dont_allow_closed_statuses
697 def test_blocked_issues_dont_allow_closed_statuses
702 blocked_issue = Issue.find(9)
698 blocked_issue = Issue.find(9)
703
699
704 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
700 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
705 assert !allowed_statuses.empty?
701 assert !allowed_statuses.empty?
706 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
702 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
707 assert closed_statuses.empty?
703 assert closed_statuses.empty?
708 end
704 end
709
705
710 def test_unblocked_issues_allow_closed_statuses
706 def test_unblocked_issues_allow_closed_statuses
711 blocking_issue = Issue.find(10)
707 blocking_issue = Issue.find(10)
712
708
713 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
709 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
714 assert !allowed_statuses.empty?
710 assert !allowed_statuses.empty?
715 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
711 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
716 assert !closed_statuses.empty?
712 assert !closed_statuses.empty?
717 end
713 end
718
714
719 def test_rescheduling_an_issue_should_reschedule_following_issue
715 def test_rescheduling_an_issue_should_reschedule_following_issue
720 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)
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)
721 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)
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)
722 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
718 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
723 assert_equal issue1.due_date + 1, issue2.reload.start_date
719 assert_equal issue1.due_date + 1, issue2.reload.start_date
724
720
725 issue1.due_date = Date.today + 5
721 issue1.due_date = Date.today + 5
726 issue1.save!
722 issue1.save!
727 assert_equal issue1.due_date + 1, issue2.reload.start_date
723 assert_equal issue1.due_date + 1, issue2.reload.start_date
728 end
724 end
729
725
730 def test_overdue
726 def test_overdue
731 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
727 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
732 assert !Issue.new(:due_date => Date.today).overdue?
728 assert !Issue.new(:due_date => Date.today).overdue?
733 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
729 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
734 assert !Issue.new(:due_date => nil).overdue?
730 assert !Issue.new(:due_date => nil).overdue?
735 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
731 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
736 end
732 end
737
733
738 context "#behind_schedule?" do
734 context "#behind_schedule?" do
739 should "be false if the issue has no start_date" do
735 should "be false if the issue has no start_date" do
740 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
736 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
741 end
737 end
742
738
743 should "be false if the issue has no end_date" do
739 should "be false if the issue has no end_date" do
744 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
740 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
745 end
741 end
746
742
747 should "be false if the issue has more done than it's calendar time" do
743 should "be false if the issue has more done than it's calendar time" do
748 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
744 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
749 end
745 end
750
746
751 should "be true if the issue hasn't been started at all" do
747 should "be true if the issue hasn't been started at all" do
752 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
748 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
753 end
749 end
754
750
755 should "be true if the issue has used more calendar time than it's done ratio" do
751 should "be true if the issue has used more calendar time than it's done ratio" do
756 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
752 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
757 end
753 end
758 end
754 end
759
755
760 context "#assignable_users" do
756 context "#assignable_users" do
761 should "be Users" do
757 should "be Users" do
762 assert_kind_of User, Issue.find(1).assignable_users.first
758 assert_kind_of User, Issue.find(1).assignable_users.first
763 end
759 end
764
760
765 should "include the issue author" do
761 should "include the issue author" do
766 project = Project.find(1)
762 project = Project.find(1)
767 non_project_member = User.generate!
763 non_project_member = User.generate!
768 issue = Issue.generate_for_project!(project, :author => non_project_member)
764 issue = Issue.generate_for_project!(project, :author => non_project_member)
769
765
770 assert issue.assignable_users.include?(non_project_member)
766 assert issue.assignable_users.include?(non_project_member)
771 end
767 end
772
768
773 should "include the current assignee" do
769 should "include the current assignee" do
774 project = Project.find(1)
770 project = Project.find(1)
775 user = User.generate!
771 user = User.generate!
776 issue = Issue.generate_for_project!(project, :assigned_to => user)
772 issue = Issue.generate_for_project!(project, :assigned_to => user)
777 user.lock!
773 user.lock!
778
774
779 assert Issue.find(issue.id).assignable_users.include?(user)
775 assert Issue.find(issue.id).assignable_users.include?(user)
780 end
776 end
781
777
782 should "not show the issue author twice" do
778 should "not show the issue author twice" do
783 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
779 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
784 assert_equal 2, assignable_user_ids.length
780 assert_equal 2, assignable_user_ids.length
785
781
786 assignable_user_ids.each do |user_id|
782 assignable_user_ids.each do |user_id|
787 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
783 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
788 end
784 end
789 end
785 end
790
786
791 context "with issue_group_assignment" do
787 context "with issue_group_assignment" do
792 should "include groups" do
788 should "include groups" do
793 issue = Issue.new(:project => Project.find(2))
789 issue = Issue.new(:project => Project.find(2))
794
790
795 with_settings :issue_group_assignment => '1' do
791 with_settings :issue_group_assignment => '1' do
796 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
792 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
797 assert issue.assignable_users.include?(Group.find(11))
793 assert issue.assignable_users.include?(Group.find(11))
798 end
794 end
799 end
795 end
800 end
796 end
801
797
802 context "without issue_group_assignment" do
798 context "without issue_group_assignment" do
803 should "not include groups" do
799 should "not include groups" do
804 issue = Issue.new(:project => Project.find(2))
800 issue = Issue.new(:project => Project.find(2))
805
801
806 with_settings :issue_group_assignment => '0' do
802 with_settings :issue_group_assignment => '0' do
807 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
803 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
808 assert !issue.assignable_users.include?(Group.find(11))
804 assert !issue.assignable_users.include?(Group.find(11))
809 end
805 end
810 end
806 end
811 end
807 end
812 end
808 end
813
809
814 def test_create_should_send_email_notification
810 def test_create_should_send_email_notification
815 ActionMailer::Base.deliveries.clear
811 ActionMailer::Base.deliveries.clear
816 issue = Issue.new(:project_id => 1, :tracker_id => 1,
812 issue = Issue.new(:project_id => 1, :tracker_id => 1,
817 :author_id => 3, :status_id => 1,
813 :author_id => 3, :status_id => 1,
818 :priority => IssuePriority.all.first,
814 :priority => IssuePriority.all.first,
819 :subject => 'test_create', :estimated_hours => '1:30')
815 :subject => 'test_create', :estimated_hours => '1:30')
820
816
821 assert issue.save
817 assert issue.save
822 assert_equal 1, ActionMailer::Base.deliveries.size
818 assert_equal 1, ActionMailer::Base.deliveries.size
823 end
819 end
824
820
825 def test_stale_issue_should_not_send_email_notification
821 def test_stale_issue_should_not_send_email_notification
826 ActionMailer::Base.deliveries.clear
822 ActionMailer::Base.deliveries.clear
827 issue = Issue.find(1)
823 issue = Issue.find(1)
828 stale = Issue.find(1)
824 stale = Issue.find(1)
829
825
830 issue.init_journal(User.find(1))
826 issue.init_journal(User.find(1))
831 issue.subject = 'Subjet update'
827 issue.subject = 'Subjet update'
832 assert issue.save
828 assert issue.save
833 assert_equal 1, ActionMailer::Base.deliveries.size
829 assert_equal 1, ActionMailer::Base.deliveries.size
834 ActionMailer::Base.deliveries.clear
830 ActionMailer::Base.deliveries.clear
835
831
836 stale.init_journal(User.find(1))
832 stale.init_journal(User.find(1))
837 stale.subject = 'Another subjet update'
833 stale.subject = 'Another subjet update'
838 assert_raise ActiveRecord::StaleObjectError do
834 assert_raise ActiveRecord::StaleObjectError do
839 stale.save
835 stale.save
840 end
836 end
841 assert ActionMailer::Base.deliveries.empty?
837 assert ActionMailer::Base.deliveries.empty?
842 end
838 end
843
839
844 def test_journalized_description
840 def test_journalized_description
845 IssueCustomField.delete_all
841 IssueCustomField.delete_all
846
842
847 i = Issue.first
843 i = Issue.first
848 old_description = i.description
844 old_description = i.description
849 new_description = "This is the new description"
845 new_description = "This is the new description"
850
846
851 i.init_journal(User.find(2))
847 i.init_journal(User.find(2))
852 i.description = new_description
848 i.description = new_description
853 assert_difference 'Journal.count', 1 do
849 assert_difference 'Journal.count', 1 do
854 assert_difference 'JournalDetail.count', 1 do
850 assert_difference 'JournalDetail.count', 1 do
855 i.save!
851 i.save!
856 end
852 end
857 end
853 end
858
854
859 detail = JournalDetail.first(:order => 'id DESC')
855 detail = JournalDetail.first(:order => 'id DESC')
860 assert_equal i, detail.journal.journalized
856 assert_equal i, detail.journal.journalized
861 assert_equal 'attr', detail.property
857 assert_equal 'attr', detail.property
862 assert_equal 'description', detail.prop_key
858 assert_equal 'description', detail.prop_key
863 assert_equal old_description, detail.old_value
859 assert_equal old_description, detail.old_value
864 assert_equal new_description, detail.value
860 assert_equal new_description, detail.value
865 end
861 end
866
862
867 def test_blank_descriptions_should_not_be_journalized
863 def test_blank_descriptions_should_not_be_journalized
868 IssueCustomField.delete_all
864 IssueCustomField.delete_all
869 Issue.update_all("description = NULL", "id=1")
865 Issue.update_all("description = NULL", "id=1")
870
866
871 i = Issue.find(1)
867 i = Issue.find(1)
872 i.init_journal(User.find(2))
868 i.init_journal(User.find(2))
873 i.subject = "blank description"
869 i.subject = "blank description"
874 i.description = "\r\n"
870 i.description = "\r\n"
875
871
876 assert_difference 'Journal.count', 1 do
872 assert_difference 'Journal.count', 1 do
877 assert_difference 'JournalDetail.count', 1 do
873 assert_difference 'JournalDetail.count', 1 do
878 i.save!
874 i.save!
879 end
875 end
880 end
876 end
881 end
877 end
882
878
883 def test_description_eol_should_be_normalized
879 def test_description_eol_should_be_normalized
884 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
880 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
885 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
881 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
886 end
882 end
887
883
888 def test_saving_twice_should_not_duplicate_journal_details
884 def test_saving_twice_should_not_duplicate_journal_details
889 i = Issue.find(:first)
885 i = Issue.find(:first)
890 i.init_journal(User.find(2), 'Some notes')
886 i.init_journal(User.find(2), 'Some notes')
891 # initial changes
887 # initial changes
892 i.subject = 'New subject'
888 i.subject = 'New subject'
893 i.done_ratio = i.done_ratio + 10
889 i.done_ratio = i.done_ratio + 10
894 assert_difference 'Journal.count' do
890 assert_difference 'Journal.count' do
895 assert i.save
891 assert i.save
896 end
892 end
897 # 1 more change
893 # 1 more change
898 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
894 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
899 assert_no_difference 'Journal.count' do
895 assert_no_difference 'Journal.count' do
900 assert_difference 'JournalDetail.count', 1 do
896 assert_difference 'JournalDetail.count', 1 do
901 i.save
897 i.save
902 end
898 end
903 end
899 end
904 # no more change
900 # no more change
905 assert_no_difference 'Journal.count' do
901 assert_no_difference 'Journal.count' do
906 assert_no_difference 'JournalDetail.count' do
902 assert_no_difference 'JournalDetail.count' do
907 i.save
903 i.save
908 end
904 end
909 end
905 end
910 end
906 end
911
907
912 def test_all_dependent_issues
908 def test_all_dependent_issues
913 IssueRelation.delete_all
909 IssueRelation.delete_all
914 assert IssueRelation.create!(:issue_from => Issue.find(1),
910 assert IssueRelation.create!(:issue_from => Issue.find(1),
915 :issue_to => Issue.find(2),
911 :issue_to => Issue.find(2),
916 :relation_type => IssueRelation::TYPE_PRECEDES)
912 :relation_type => IssueRelation::TYPE_PRECEDES)
917 assert IssueRelation.create!(:issue_from => Issue.find(2),
913 assert IssueRelation.create!(:issue_from => Issue.find(2),
918 :issue_to => Issue.find(3),
914 :issue_to => Issue.find(3),
919 :relation_type => IssueRelation::TYPE_PRECEDES)
915 :relation_type => IssueRelation::TYPE_PRECEDES)
920 assert IssueRelation.create!(:issue_from => Issue.find(3),
916 assert IssueRelation.create!(:issue_from => Issue.find(3),
921 :issue_to => Issue.find(8),
917 :issue_to => Issue.find(8),
922 :relation_type => IssueRelation::TYPE_PRECEDES)
918 :relation_type => IssueRelation::TYPE_PRECEDES)
923
919
924 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
920 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
925 end
921 end
926
922
927 def test_all_dependent_issues_with_persistent_circular_dependency
923 def test_all_dependent_issues_with_persistent_circular_dependency
928 IssueRelation.delete_all
924 IssueRelation.delete_all
929 assert IssueRelation.create!(:issue_from => Issue.find(1),
925 assert IssueRelation.create!(:issue_from => Issue.find(1),
930 :issue_to => Issue.find(2),
926 :issue_to => Issue.find(2),
931 :relation_type => IssueRelation::TYPE_PRECEDES)
927 :relation_type => IssueRelation::TYPE_PRECEDES)
932 assert IssueRelation.create!(:issue_from => Issue.find(2),
928 assert IssueRelation.create!(:issue_from => Issue.find(2),
933 :issue_to => Issue.find(3),
929 :issue_to => Issue.find(3),
934 :relation_type => IssueRelation::TYPE_PRECEDES)
930 :relation_type => IssueRelation::TYPE_PRECEDES)
935 # Validation skipping
931 # Validation skipping
936 assert IssueRelation.new(:issue_from => Issue.find(3),
932 assert IssueRelation.new(:issue_from => Issue.find(3),
937 :issue_to => Issue.find(1),
933 :issue_to => Issue.find(1),
938 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
934 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
939
935
940 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
936 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
941 end
937 end
942
938
943 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
939 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
944 IssueRelation.delete_all
940 IssueRelation.delete_all
945 assert IssueRelation.create!(:issue_from => Issue.find(1),
941 assert IssueRelation.create!(:issue_from => Issue.find(1),
946 :issue_to => Issue.find(2),
942 :issue_to => Issue.find(2),
947 :relation_type => IssueRelation::TYPE_RELATES)
943 :relation_type => IssueRelation::TYPE_RELATES)
948 assert IssueRelation.create!(:issue_from => Issue.find(2),
944 assert IssueRelation.create!(:issue_from => Issue.find(2),
949 :issue_to => Issue.find(3),
945 :issue_to => Issue.find(3),
950 :relation_type => IssueRelation::TYPE_RELATES)
946 :relation_type => IssueRelation::TYPE_RELATES)
951 assert IssueRelation.create!(:issue_from => Issue.find(3),
947 assert IssueRelation.create!(:issue_from => Issue.find(3),
952 :issue_to => Issue.find(8),
948 :issue_to => Issue.find(8),
953 :relation_type => IssueRelation::TYPE_RELATES)
949 :relation_type => IssueRelation::TYPE_RELATES)
954 # Validation skipping
950 # Validation skipping
955 assert IssueRelation.new(:issue_from => Issue.find(8),
951 assert IssueRelation.new(:issue_from => Issue.find(8),
956 :issue_to => Issue.find(2),
952 :issue_to => Issue.find(2),
957 :relation_type => IssueRelation::TYPE_RELATES).save(false)
953 :relation_type => IssueRelation::TYPE_RELATES).save(false)
958 assert IssueRelation.new(:issue_from => Issue.find(3),
954 assert IssueRelation.new(:issue_from => Issue.find(3),
959 :issue_to => Issue.find(1),
955 :issue_to => Issue.find(1),
960 :relation_type => IssueRelation::TYPE_RELATES).save(false)
956 :relation_type => IssueRelation::TYPE_RELATES).save(false)
961
957
962 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
958 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
963 end
959 end
964
960
965 context "#done_ratio" do
961 context "#done_ratio" do
966 setup do
962 setup do
967 @issue = Issue.find(1)
963 @issue = Issue.find(1)
968 @issue_status = IssueStatus.find(1)
964 @issue_status = IssueStatus.find(1)
969 @issue_status.update_attribute(:default_done_ratio, 50)
965 @issue_status.update_attribute(:default_done_ratio, 50)
970 @issue2 = Issue.find(2)
966 @issue2 = Issue.find(2)
971 @issue_status2 = IssueStatus.find(2)
967 @issue_status2 = IssueStatus.find(2)
972 @issue_status2.update_attribute(:default_done_ratio, 0)
968 @issue_status2.update_attribute(:default_done_ratio, 0)
973 end
969 end
974
970
975 teardown do
971 teardown do
976 Setting.issue_done_ratio = 'issue_field'
972 Setting.issue_done_ratio = 'issue_field'
977 end
973 end
978
974
979 context "with Setting.issue_done_ratio using the issue_field" do
975 context "with Setting.issue_done_ratio using the issue_field" do
980 setup do
976 setup do
981 Setting.issue_done_ratio = 'issue_field'
977 Setting.issue_done_ratio = 'issue_field'
982 end
978 end
983
979
984 should "read the issue's field" do
980 should "read the issue's field" do
985 assert_equal 0, @issue.done_ratio
981 assert_equal 0, @issue.done_ratio
986 assert_equal 30, @issue2.done_ratio
982 assert_equal 30, @issue2.done_ratio
987 end
983 end
988 end
984 end
989
985
990 context "with Setting.issue_done_ratio using the issue_status" do
986 context "with Setting.issue_done_ratio using the issue_status" do
991 setup do
987 setup do
992 Setting.issue_done_ratio = 'issue_status'
988 Setting.issue_done_ratio = 'issue_status'
993 end
989 end
994
990
995 should "read the Issue Status's default done ratio" do
991 should "read the Issue Status's default done ratio" do
996 assert_equal 50, @issue.done_ratio
992 assert_equal 50, @issue.done_ratio
997 assert_equal 0, @issue2.done_ratio
993 assert_equal 0, @issue2.done_ratio
998 end
994 end
999 end
995 end
1000 end
996 end
1001
997
1002 context "#update_done_ratio_from_issue_status" do
998 context "#update_done_ratio_from_issue_status" do
1003 setup do
999 setup do
1004 @issue = Issue.find(1)
1000 @issue = Issue.find(1)
1005 @issue_status = IssueStatus.find(1)
1001 @issue_status = IssueStatus.find(1)
1006 @issue_status.update_attribute(:default_done_ratio, 50)
1002 @issue_status.update_attribute(:default_done_ratio, 50)
1007 @issue2 = Issue.find(2)
1003 @issue2 = Issue.find(2)
1008 @issue_status2 = IssueStatus.find(2)
1004 @issue_status2 = IssueStatus.find(2)
1009 @issue_status2.update_attribute(:default_done_ratio, 0)
1005 @issue_status2.update_attribute(:default_done_ratio, 0)
1010 end
1006 end
1011
1007
1012 context "with Setting.issue_done_ratio using the issue_field" do
1008 context "with Setting.issue_done_ratio using the issue_field" do
1013 setup do
1009 setup do
1014 Setting.issue_done_ratio = 'issue_field'
1010 Setting.issue_done_ratio = 'issue_field'
1015 end
1011 end
1016
1012
1017 should "not change the issue" do
1013 should "not change the issue" do
1018 @issue.update_done_ratio_from_issue_status
1014 @issue.update_done_ratio_from_issue_status
1019 @issue2.update_done_ratio_from_issue_status
1015 @issue2.update_done_ratio_from_issue_status
1020
1016
1021 assert_equal 0, @issue.read_attribute(:done_ratio)
1017 assert_equal 0, @issue.read_attribute(:done_ratio)
1022 assert_equal 30, @issue2.read_attribute(:done_ratio)
1018 assert_equal 30, @issue2.read_attribute(:done_ratio)
1023 end
1019 end
1024 end
1020 end
1025
1021
1026 context "with Setting.issue_done_ratio using the issue_status" do
1022 context "with Setting.issue_done_ratio using the issue_status" do
1027 setup do
1023 setup do
1028 Setting.issue_done_ratio = 'issue_status'
1024 Setting.issue_done_ratio = 'issue_status'
1029 end
1025 end
1030
1026
1031 should "change the issue's done ratio" do
1027 should "change the issue's done ratio" do
1032 @issue.update_done_ratio_from_issue_status
1028 @issue.update_done_ratio_from_issue_status
1033 @issue2.update_done_ratio_from_issue_status
1029 @issue2.update_done_ratio_from_issue_status
1034
1030
1035 assert_equal 50, @issue.read_attribute(:done_ratio)
1031 assert_equal 50, @issue.read_attribute(:done_ratio)
1036 assert_equal 0, @issue2.read_attribute(:done_ratio)
1032 assert_equal 0, @issue2.read_attribute(:done_ratio)
1037 end
1033 end
1038 end
1034 end
1039 end
1035 end
1040
1036
1041 test "#by_tracker" do
1037 test "#by_tracker" do
1042 User.current = User.anonymous
1038 User.current = User.anonymous
1043 groups = Issue.by_tracker(Project.find(1))
1039 groups = Issue.by_tracker(Project.find(1))
1044 assert_equal 3, groups.size
1040 assert_equal 3, groups.size
1045 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1041 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1046 end
1042 end
1047
1043
1048 test "#by_version" do
1044 test "#by_version" do
1049 User.current = User.anonymous
1045 User.current = User.anonymous
1050 groups = Issue.by_version(Project.find(1))
1046 groups = Issue.by_version(Project.find(1))
1051 assert_equal 3, groups.size
1047 assert_equal 3, groups.size
1052 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1048 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1053 end
1049 end
1054
1050
1055 test "#by_priority" do
1051 test "#by_priority" do
1056 User.current = User.anonymous
1052 User.current = User.anonymous
1057 groups = Issue.by_priority(Project.find(1))
1053 groups = Issue.by_priority(Project.find(1))
1058 assert_equal 4, groups.size
1054 assert_equal 4, groups.size
1059 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1055 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1060 end
1056 end
1061
1057
1062 test "#by_category" do
1058 test "#by_category" do
1063 User.current = User.anonymous
1059 User.current = User.anonymous
1064 groups = Issue.by_category(Project.find(1))
1060 groups = Issue.by_category(Project.find(1))
1065 assert_equal 2, groups.size
1061 assert_equal 2, groups.size
1066 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1062 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1067 end
1063 end
1068
1064
1069 test "#by_assigned_to" do
1065 test "#by_assigned_to" do
1070 User.current = User.anonymous
1066 User.current = User.anonymous
1071 groups = Issue.by_assigned_to(Project.find(1))
1067 groups = Issue.by_assigned_to(Project.find(1))
1072 assert_equal 2, groups.size
1068 assert_equal 2, groups.size
1073 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1069 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1074 end
1070 end
1075
1071
1076 test "#by_author" do
1072 test "#by_author" do
1077 User.current = User.anonymous
1073 User.current = User.anonymous
1078 groups = Issue.by_author(Project.find(1))
1074 groups = Issue.by_author(Project.find(1))
1079 assert_equal 4, groups.size
1075 assert_equal 4, groups.size
1080 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1076 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1081 end
1077 end
1082
1078
1083 test "#by_subproject" do
1079 test "#by_subproject" do
1084 User.current = User.anonymous
1080 User.current = User.anonymous
1085 groups = Issue.by_subproject(Project.find(1))
1081 groups = Issue.by_subproject(Project.find(1))
1086 # Private descendant not visible
1082 # Private descendant not visible
1087 assert_equal 1, groups.size
1083 assert_equal 1, groups.size
1088 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1084 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1089 end
1085 end
1090
1086
1091 context ".allowed_target_projects_on_move" do
1087 context ".allowed_target_projects_on_move" do
1092 should "return all active projects for admin users" do
1088 should "return all active projects for admin users" do
1093 User.current = User.find(1)
1089 User.current = User.find(1)
1094 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1090 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1095 end
1091 end
1096
1092
1097 should "return allowed projects for non admin users" do
1093 should "return allowed projects for non admin users" do
1098 User.current = User.find(2)
1094 User.current = User.find(2)
1099 Role.non_member.remove_permission! :move_issues
1095 Role.non_member.remove_permission! :move_issues
1100 assert_equal 3, Issue.allowed_target_projects_on_move.size
1096 assert_equal 3, Issue.allowed_target_projects_on_move.size
1101
1097
1102 Role.non_member.add_permission! :move_issues
1098 Role.non_member.add_permission! :move_issues
1103 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1099 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1104 end
1100 end
1105 end
1101 end
1106
1102
1107 def test_recently_updated_with_limit_scopes
1103 def test_recently_updated_with_limit_scopes
1108 #should return the last updated issue
1104 #should return the last updated issue
1109 assert_equal 1, Issue.recently_updated.with_limit(1).length
1105 assert_equal 1, Issue.recently_updated.with_limit(1).length
1110 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1106 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1111 end
1107 end
1112
1108
1113 def test_on_active_projects_scope
1109 def test_on_active_projects_scope
1114 assert Project.find(2).archive
1110 assert Project.find(2).archive
1115
1111
1116 before = Issue.on_active_project.length
1112 before = Issue.on_active_project.length
1117 # test inclusion to results
1113 # test inclusion to results
1118 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1114 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1119 assert_equal before + 1, Issue.on_active_project.length
1115 assert_equal before + 1, Issue.on_active_project.length
1120
1116
1121 # Move to an archived project
1117 # Move to an archived project
1122 issue.project = Project.find(2)
1118 issue.project = Project.find(2)
1123 assert issue.save
1119 assert issue.save
1124 assert_equal before, Issue.on_active_project.length
1120 assert_equal before, Issue.on_active_project.length
1125 end
1121 end
1126
1122
1127 context "Issue#recipients" do
1123 context "Issue#recipients" do
1128 setup do
1124 setup do
1129 @project = Project.find(1)
1125 @project = Project.find(1)
1130 @author = User.generate_with_protected!
1126 @author = User.generate_with_protected!
1131 @assignee = User.generate_with_protected!
1127 @assignee = User.generate_with_protected!
1132 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1128 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1133 end
1129 end
1134
1130
1135 should "include project recipients" do
1131 should "include project recipients" do
1136 assert @project.recipients.present?
1132 assert @project.recipients.present?
1137 @project.recipients.each do |project_recipient|
1133 @project.recipients.each do |project_recipient|
1138 assert @issue.recipients.include?(project_recipient)
1134 assert @issue.recipients.include?(project_recipient)
1139 end
1135 end
1140 end
1136 end
1141
1137
1142 should "include the author if the author is active" do
1138 should "include the author if the author is active" do
1143 assert @issue.author, "No author set for Issue"
1139 assert @issue.author, "No author set for Issue"
1144 assert @issue.recipients.include?(@issue.author.mail)
1140 assert @issue.recipients.include?(@issue.author.mail)
1145 end
1141 end
1146
1142
1147 should "include the assigned to user if the assigned to user is active" do
1143 should "include the assigned to user if the assigned to user is active" do
1148 assert @issue.assigned_to, "No assigned_to set for Issue"
1144 assert @issue.assigned_to, "No assigned_to set for Issue"
1149 assert @issue.recipients.include?(@issue.assigned_to.mail)
1145 assert @issue.recipients.include?(@issue.assigned_to.mail)
1150 end
1146 end
1151
1147
1152 should "not include users who opt out of all email" do
1148 should "not include users who opt out of all email" do
1153 @author.update_attribute(:mail_notification, :none)
1149 @author.update_attribute(:mail_notification, :none)
1154
1150
1155 assert !@issue.recipients.include?(@issue.author.mail)
1151 assert !@issue.recipients.include?(@issue.author.mail)
1156 end
1152 end
1157
1153
1158 should "not include the issue author if they are only notified of assigned issues" do
1154 should "not include the issue author if they are only notified of assigned issues" do
1159 @author.update_attribute(:mail_notification, :only_assigned)
1155 @author.update_attribute(:mail_notification, :only_assigned)
1160
1156
1161 assert !@issue.recipients.include?(@issue.author.mail)
1157 assert !@issue.recipients.include?(@issue.author.mail)
1162 end
1158 end
1163
1159
1164 should "not include the assigned user if they are only notified of owned issues" do
1160 should "not include the assigned user if they are only notified of owned issues" do
1165 @assignee.update_attribute(:mail_notification, :only_owner)
1161 @assignee.update_attribute(:mail_notification, :only_owner)
1166
1162
1167 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1163 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1168 end
1164 end
1169
1165
1170 end
1166 end
1171 end
1167 end
General Comments 0
You need to be logged in to leave comments. Login now