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