##// END OF EJS Templates
Added tests for Issue#by_X finders...
Eric Davis -
r3250:112fc993114b
parent child
Show More
@@ -1,592 +1,634
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
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 :versions,
23 :versions,
24 :issue_statuses, :issue_categories, :issue_relations, :workflows,
24 :issue_statuses, :issue_categories, :issue_relations, :workflows,
25 :enumerations,
25 :enumerations,
26 :issues,
26 :issues,
27 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
27 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
28 :time_entries
28 :time_entries
29
29
30 def test_create
30 def test_create
31 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :description => 'IssueTest#test_create', :estimated_hours => '1:30')
31 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :description => 'IssueTest#test_create', :estimated_hours => '1:30')
32 assert issue.save
32 assert issue.save
33 issue.reload
33 issue.reload
34 assert_equal 1.5, issue.estimated_hours
34 assert_equal 1.5, issue.estimated_hours
35 end
35 end
36
36
37 def test_create_minimal
37 def test_create_minimal
38 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create')
38 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create')
39 assert issue.save
39 assert issue.save
40 assert issue.description.nil?
40 assert issue.description.nil?
41 end
41 end
42
42
43 def test_create_with_required_custom_field
43 def test_create_with_required_custom_field
44 field = IssueCustomField.find_by_name('Database')
44 field = IssueCustomField.find_by_name('Database')
45 field.update_attribute(:is_required, true)
45 field.update_attribute(:is_required, true)
46
46
47 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field')
47 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field')
48 assert issue.available_custom_fields.include?(field)
48 assert issue.available_custom_fields.include?(field)
49 # No value for the custom field
49 # No value for the custom field
50 assert !issue.save
50 assert !issue.save
51 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
51 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
52 # Blank value
52 # Blank value
53 issue.custom_field_values = { field.id => '' }
53 issue.custom_field_values = { field.id => '' }
54 assert !issue.save
54 assert !issue.save
55 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
55 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
56 # Invalid value
56 # Invalid value
57 issue.custom_field_values = { field.id => 'SQLServer' }
57 issue.custom_field_values = { field.id => 'SQLServer' }
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 # Valid value
60 # Valid value
61 issue.custom_field_values = { field.id => 'PostgreSQL' }
61 issue.custom_field_values = { field.id => 'PostgreSQL' }
62 assert issue.save
62 assert issue.save
63 issue.reload
63 issue.reload
64 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
64 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
65 end
65 end
66
66
67 def test_visible_scope_for_anonymous
67 def test_visible_scope_for_anonymous
68 # Anonymous user should see issues of public projects only
68 # Anonymous user should see issues of public projects only
69 issues = Issue.visible(User.anonymous).all
69 issues = Issue.visible(User.anonymous).all
70 assert issues.any?
70 assert issues.any?
71 assert_nil issues.detect {|issue| !issue.project.is_public?}
71 assert_nil issues.detect {|issue| !issue.project.is_public?}
72 # Anonymous user should not see issues without permission
72 # Anonymous user should not see issues without permission
73 Role.anonymous.remove_permission!(:view_issues)
73 Role.anonymous.remove_permission!(:view_issues)
74 issues = Issue.visible(User.anonymous).all
74 issues = Issue.visible(User.anonymous).all
75 assert issues.empty?
75 assert issues.empty?
76 end
76 end
77
77
78 def test_visible_scope_for_user
78 def test_visible_scope_for_user
79 user = User.find(9)
79 user = User.find(9)
80 assert user.projects.empty?
80 assert user.projects.empty?
81 # Non member user should see issues of public projects only
81 # Non member user should see issues of public projects only
82 issues = Issue.visible(user).all
82 issues = Issue.visible(user).all
83 assert issues.any?
83 assert issues.any?
84 assert_nil issues.detect {|issue| !issue.project.is_public?}
84 assert_nil issues.detect {|issue| !issue.project.is_public?}
85 # Non member user should not see issues without permission
85 # Non member user should not see issues without permission
86 Role.non_member.remove_permission!(:view_issues)
86 Role.non_member.remove_permission!(:view_issues)
87 user.reload
87 user.reload
88 issues = Issue.visible(user).all
88 issues = Issue.visible(user).all
89 assert issues.empty?
89 assert issues.empty?
90 # User should see issues of projects for which he has view_issues permissions only
90 # User should see issues of projects for which he has view_issues permissions only
91 Member.create!(:principal => user, :project_id => 2, :role_ids => [1])
91 Member.create!(:principal => user, :project_id => 2, :role_ids => [1])
92 user.reload
92 user.reload
93 issues = Issue.visible(user).all
93 issues = Issue.visible(user).all
94 assert issues.any?
94 assert issues.any?
95 assert_nil issues.detect {|issue| issue.project_id != 2}
95 assert_nil issues.detect {|issue| issue.project_id != 2}
96 end
96 end
97
97
98 def test_visible_scope_for_admin
98 def test_visible_scope_for_admin
99 user = User.find(1)
99 user = User.find(1)
100 user.members.each(&:destroy)
100 user.members.each(&:destroy)
101 assert user.projects.empty?
101 assert user.projects.empty?
102 issues = Issue.visible(user).all
102 issues = Issue.visible(user).all
103 assert issues.any?
103 assert issues.any?
104 # Admin should see issues on private projects that he does not belong to
104 # Admin should see issues on private projects that he does not belong to
105 assert issues.detect {|issue| !issue.project.is_public?}
105 assert issues.detect {|issue| !issue.project.is_public?}
106 end
106 end
107
107
108 def test_errors_full_messages_should_include_custom_fields_errors
108 def test_errors_full_messages_should_include_custom_fields_errors
109 field = IssueCustomField.find_by_name('Database')
109 field = IssueCustomField.find_by_name('Database')
110
110
111 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field')
111 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'test_create', :description => 'IssueTest#test_create_with_required_custom_field')
112 assert issue.available_custom_fields.include?(field)
112 assert issue.available_custom_fields.include?(field)
113 # Invalid value
113 # Invalid value
114 issue.custom_field_values = { field.id => 'SQLServer' }
114 issue.custom_field_values = { field.id => 'SQLServer' }
115
115
116 assert !issue.valid?
116 assert !issue.valid?
117 assert_equal 1, issue.errors.full_messages.size
117 assert_equal 1, issue.errors.full_messages.size
118 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", issue.errors.full_messages.first
118 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", issue.errors.full_messages.first
119 end
119 end
120
120
121 def test_update_issue_with_required_custom_field
121 def test_update_issue_with_required_custom_field
122 field = IssueCustomField.find_by_name('Database')
122 field = IssueCustomField.find_by_name('Database')
123 field.update_attribute(:is_required, true)
123 field.update_attribute(:is_required, true)
124
124
125 issue = Issue.find(1)
125 issue = Issue.find(1)
126 assert_nil issue.custom_value_for(field)
126 assert_nil issue.custom_value_for(field)
127 assert issue.available_custom_fields.include?(field)
127 assert issue.available_custom_fields.include?(field)
128 # No change to custom values, issue can be saved
128 # No change to custom values, issue can be saved
129 assert issue.save
129 assert issue.save
130 # Blank value
130 # Blank value
131 issue.custom_field_values = { field.id => '' }
131 issue.custom_field_values = { field.id => '' }
132 assert !issue.save
132 assert !issue.save
133 # Valid value
133 # Valid value
134 issue.custom_field_values = { field.id => 'PostgreSQL' }
134 issue.custom_field_values = { field.id => 'PostgreSQL' }
135 assert issue.save
135 assert issue.save
136 issue.reload
136 issue.reload
137 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
137 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
138 end
138 end
139
139
140 def test_should_not_update_attributes_if_custom_fields_validation_fails
140 def test_should_not_update_attributes_if_custom_fields_validation_fails
141 issue = Issue.find(1)
141 issue = Issue.find(1)
142 field = IssueCustomField.find_by_name('Database')
142 field = IssueCustomField.find_by_name('Database')
143 assert issue.available_custom_fields.include?(field)
143 assert issue.available_custom_fields.include?(field)
144
144
145 issue.custom_field_values = { field.id => 'Invalid' }
145 issue.custom_field_values = { field.id => 'Invalid' }
146 issue.subject = 'Should be not be saved'
146 issue.subject = 'Should be not be saved'
147 assert !issue.save
147 assert !issue.save
148
148
149 issue.reload
149 issue.reload
150 assert_equal "Can't print recipes", issue.subject
150 assert_equal "Can't print recipes", issue.subject
151 end
151 end
152
152
153 def test_should_not_recreate_custom_values_objects_on_update
153 def test_should_not_recreate_custom_values_objects_on_update
154 field = IssueCustomField.find_by_name('Database')
154 field = IssueCustomField.find_by_name('Database')
155
155
156 issue = Issue.find(1)
156 issue = Issue.find(1)
157 issue.custom_field_values = { field.id => 'PostgreSQL' }
157 issue.custom_field_values = { field.id => 'PostgreSQL' }
158 assert issue.save
158 assert issue.save
159 custom_value = issue.custom_value_for(field)
159 custom_value = issue.custom_value_for(field)
160 issue.reload
160 issue.reload
161 issue.custom_field_values = { field.id => 'MySQL' }
161 issue.custom_field_values = { field.id => 'MySQL' }
162 assert issue.save
162 assert issue.save
163 issue.reload
163 issue.reload
164 assert_equal custom_value.id, issue.custom_value_for(field).id
164 assert_equal custom_value.id, issue.custom_value_for(field).id
165 end
165 end
166
166
167 def test_assigning_tracker_id_should_reload_custom_fields_values
167 def test_assigning_tracker_id_should_reload_custom_fields_values
168 issue = Issue.new(:project => Project.find(1))
168 issue = Issue.new(:project => Project.find(1))
169 assert issue.custom_field_values.empty?
169 assert issue.custom_field_values.empty?
170 issue.tracker_id = 1
170 issue.tracker_id = 1
171 assert issue.custom_field_values.any?
171 assert issue.custom_field_values.any?
172 end
172 end
173
173
174 def test_assigning_attributes_should_assign_tracker_id_first
174 def test_assigning_attributes_should_assign_tracker_id_first
175 attributes = ActiveSupport::OrderedHash.new
175 attributes = ActiveSupport::OrderedHash.new
176 attributes['custom_field_values'] = { '1' => 'MySQL' }
176 attributes['custom_field_values'] = { '1' => 'MySQL' }
177 attributes['tracker_id'] = '1'
177 attributes['tracker_id'] = '1'
178 issue = Issue.new(:project => Project.find(1))
178 issue = Issue.new(:project => Project.find(1))
179 issue.attributes = attributes
179 issue.attributes = attributes
180 assert_not_nil issue.custom_value_for(1)
180 assert_not_nil issue.custom_value_for(1)
181 assert_equal 'MySQL', issue.custom_value_for(1).value
181 assert_equal 'MySQL', issue.custom_value_for(1).value
182 end
182 end
183
183
184 def test_should_update_issue_with_disabled_tracker
184 def test_should_update_issue_with_disabled_tracker
185 p = Project.find(1)
185 p = Project.find(1)
186 issue = Issue.find(1)
186 issue = Issue.find(1)
187
187
188 p.trackers.delete(issue.tracker)
188 p.trackers.delete(issue.tracker)
189 assert !p.trackers.include?(issue.tracker)
189 assert !p.trackers.include?(issue.tracker)
190
190
191 issue.reload
191 issue.reload
192 issue.subject = 'New subject'
192 issue.subject = 'New subject'
193 assert issue.save
193 assert issue.save
194 end
194 end
195
195
196 def test_should_not_set_a_disabled_tracker
196 def test_should_not_set_a_disabled_tracker
197 p = Project.find(1)
197 p = Project.find(1)
198 p.trackers.delete(Tracker.find(2))
198 p.trackers.delete(Tracker.find(2))
199
199
200 issue = Issue.find(1)
200 issue = Issue.find(1)
201 issue.tracker_id = 2
201 issue.tracker_id = 2
202 issue.subject = 'New subject'
202 issue.subject = 'New subject'
203 assert !issue.save
203 assert !issue.save
204 assert_not_nil issue.errors.on(:tracker_id)
204 assert_not_nil issue.errors.on(:tracker_id)
205 end
205 end
206
206
207 def test_category_based_assignment
207 def test_category_based_assignment
208 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1)
208 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Assignment test', :description => 'Assignment test', :category_id => 1)
209 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
209 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
210 end
210 end
211
211
212 def test_copy
212 def test_copy
213 issue = Issue.new.copy_from(1)
213 issue = Issue.new.copy_from(1)
214 assert issue.save
214 assert issue.save
215 issue.reload
215 issue.reload
216 orig = Issue.find(1)
216 orig = Issue.find(1)
217 assert_equal orig.subject, issue.subject
217 assert_equal orig.subject, issue.subject
218 assert_equal orig.tracker, issue.tracker
218 assert_equal orig.tracker, issue.tracker
219 assert_equal "125", issue.custom_value_for(2).value
219 assert_equal "125", issue.custom_value_for(2).value
220 end
220 end
221
221
222 def test_copy_should_copy_status
222 def test_copy_should_copy_status
223 orig = Issue.find(8)
223 orig = Issue.find(8)
224 assert orig.status != IssueStatus.default
224 assert orig.status != IssueStatus.default
225
225
226 issue = Issue.new.copy_from(orig)
226 issue = Issue.new.copy_from(orig)
227 assert issue.save
227 assert issue.save
228 issue.reload
228 issue.reload
229 assert_equal orig.status, issue.status
229 assert_equal orig.status, issue.status
230 end
230 end
231
231
232 def test_should_close_duplicates
232 def test_should_close_duplicates
233 # Create 3 issues
233 # Create 3 issues
234 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
234 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
235 assert issue1.save
235 assert issue1.save
236 issue2 = issue1.clone
236 issue2 = issue1.clone
237 assert issue2.save
237 assert issue2.save
238 issue3 = issue1.clone
238 issue3 = issue1.clone
239 assert issue3.save
239 assert issue3.save
240
240
241 # 2 is a dupe of 1
241 # 2 is a dupe of 1
242 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
242 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
243 # And 3 is a dupe of 2
243 # And 3 is a dupe of 2
244 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
244 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
245 # And 3 is a dupe of 1 (circular duplicates)
245 # And 3 is a dupe of 1 (circular duplicates)
246 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
246 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
247
247
248 assert issue1.reload.duplicates.include?(issue2)
248 assert issue1.reload.duplicates.include?(issue2)
249
249
250 # Closing issue 1
250 # Closing issue 1
251 issue1.init_journal(User.find(:first), "Closing issue1")
251 issue1.init_journal(User.find(:first), "Closing issue1")
252 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
252 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
253 assert issue1.save
253 assert issue1.save
254 # 2 and 3 should be also closed
254 # 2 and 3 should be also closed
255 assert issue2.reload.closed?
255 assert issue2.reload.closed?
256 assert issue3.reload.closed?
256 assert issue3.reload.closed?
257 end
257 end
258
258
259 def test_should_not_close_duplicated_issue
259 def test_should_not_close_duplicated_issue
260 # Create 3 issues
260 # Create 3 issues
261 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
261 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
262 assert issue1.save
262 assert issue1.save
263 issue2 = issue1.clone
263 issue2 = issue1.clone
264 assert issue2.save
264 assert issue2.save
265
265
266 # 2 is a dupe of 1
266 # 2 is a dupe of 1
267 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
267 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
268 # 2 is a dup of 1 but 1 is not a duplicate of 2
268 # 2 is a dup of 1 but 1 is not a duplicate of 2
269 assert !issue2.reload.duplicates.include?(issue1)
269 assert !issue2.reload.duplicates.include?(issue1)
270
270
271 # Closing issue 2
271 # Closing issue 2
272 issue2.init_journal(User.find(:first), "Closing issue2")
272 issue2.init_journal(User.find(:first), "Closing issue2")
273 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
273 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
274 assert issue2.save
274 assert issue2.save
275 # 1 should not be also closed
275 # 1 should not be also closed
276 assert !issue1.reload.closed?
276 assert !issue1.reload.closed?
277 end
277 end
278
278
279 def test_assignable_versions
279 def test_assignable_versions
280 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
280 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
281 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
281 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
282 end
282 end
283
283
284 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
284 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
285 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
285 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
286 assert !issue.save
286 assert !issue.save
287 assert_not_nil issue.errors.on(:fixed_version_id)
287 assert_not_nil issue.errors.on(:fixed_version_id)
288 end
288 end
289
289
290 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
290 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
291 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
291 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
292 assert !issue.save
292 assert !issue.save
293 assert_not_nil issue.errors.on(:fixed_version_id)
293 assert_not_nil issue.errors.on(:fixed_version_id)
294 end
294 end
295
295
296 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
296 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
297 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
297 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
298 assert issue.save
298 assert issue.save
299 end
299 end
300
300
301 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
301 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
302 issue = Issue.find(11)
302 issue = Issue.find(11)
303 assert_equal 'closed', issue.fixed_version.status
303 assert_equal 'closed', issue.fixed_version.status
304 issue.subject = 'Subject changed'
304 issue.subject = 'Subject changed'
305 assert issue.save
305 assert issue.save
306 end
306 end
307
307
308 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
308 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
309 issue = Issue.find(11)
309 issue = Issue.find(11)
310 issue.status_id = 1
310 issue.status_id = 1
311 assert !issue.save
311 assert !issue.save
312 assert_not_nil issue.errors.on_base
312 assert_not_nil issue.errors.on_base
313 end
313 end
314
314
315 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
315 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
316 issue = Issue.find(11)
316 issue = Issue.find(11)
317 issue.status_id = 1
317 issue.status_id = 1
318 issue.fixed_version_id = 3
318 issue.fixed_version_id = 3
319 assert issue.save
319 assert issue.save
320 end
320 end
321
321
322 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
322 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
323 issue = Issue.find(12)
323 issue = Issue.find(12)
324 assert_equal 'locked', issue.fixed_version.status
324 assert_equal 'locked', issue.fixed_version.status
325 issue.status_id = 1
325 issue.status_id = 1
326 assert issue.save
326 assert issue.save
327 end
327 end
328
328
329 def test_move_to_another_project_with_same_category
329 def test_move_to_another_project_with_same_category
330 issue = Issue.find(1)
330 issue = Issue.find(1)
331 assert issue.move_to(Project.find(2))
331 assert issue.move_to(Project.find(2))
332 issue.reload
332 issue.reload
333 assert_equal 2, issue.project_id
333 assert_equal 2, issue.project_id
334 # Category changes
334 # Category changes
335 assert_equal 4, issue.category_id
335 assert_equal 4, issue.category_id
336 # Make sure time entries were move to the target project
336 # Make sure time entries were move to the target project
337 assert_equal 2, issue.time_entries.first.project_id
337 assert_equal 2, issue.time_entries.first.project_id
338 end
338 end
339
339
340 def test_move_to_another_project_without_same_category
340 def test_move_to_another_project_without_same_category
341 issue = Issue.find(2)
341 issue = Issue.find(2)
342 assert issue.move_to(Project.find(2))
342 assert issue.move_to(Project.find(2))
343 issue.reload
343 issue.reload
344 assert_equal 2, issue.project_id
344 assert_equal 2, issue.project_id
345 # Category cleared
345 # Category cleared
346 assert_nil issue.category_id
346 assert_nil issue.category_id
347 end
347 end
348
348
349 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
349 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
350 issue = Issue.find(1)
350 issue = Issue.find(1)
351 issue.update_attribute(:fixed_version_id, 1)
351 issue.update_attribute(:fixed_version_id, 1)
352 assert issue.move_to(Project.find(2))
352 assert issue.move_to(Project.find(2))
353 issue.reload
353 issue.reload
354 assert_equal 2, issue.project_id
354 assert_equal 2, issue.project_id
355 # Cleared fixed_version
355 # Cleared fixed_version
356 assert_equal nil, issue.fixed_version
356 assert_equal nil, issue.fixed_version
357 end
357 end
358
358
359 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
359 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
360 issue = Issue.find(1)
360 issue = Issue.find(1)
361 issue.update_attribute(:fixed_version_id, 4)
361 issue.update_attribute(:fixed_version_id, 4)
362 assert issue.move_to(Project.find(5))
362 assert issue.move_to(Project.find(5))
363 issue.reload
363 issue.reload
364 assert_equal 5, issue.project_id
364 assert_equal 5, issue.project_id
365 # Keep fixed_version
365 # Keep fixed_version
366 assert_equal 4, issue.fixed_version_id
366 assert_equal 4, issue.fixed_version_id
367 end
367 end
368
368
369 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
369 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
370 issue = Issue.find(1)
370 issue = Issue.find(1)
371 issue.update_attribute(:fixed_version_id, 1)
371 issue.update_attribute(:fixed_version_id, 1)
372 assert issue.move_to(Project.find(5))
372 assert issue.move_to(Project.find(5))
373 issue.reload
373 issue.reload
374 assert_equal 5, issue.project_id
374 assert_equal 5, issue.project_id
375 # Cleared fixed_version
375 # Cleared fixed_version
376 assert_equal nil, issue.fixed_version
376 assert_equal nil, issue.fixed_version
377 end
377 end
378
378
379 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
379 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
380 issue = Issue.find(1)
380 issue = Issue.find(1)
381 issue.update_attribute(:fixed_version_id, 7)
381 issue.update_attribute(:fixed_version_id, 7)
382 assert issue.move_to(Project.find(2))
382 assert issue.move_to(Project.find(2))
383 issue.reload
383 issue.reload
384 assert_equal 2, issue.project_id
384 assert_equal 2, issue.project_id
385 # Keep fixed_version
385 # Keep fixed_version
386 assert_equal 7, issue.fixed_version_id
386 assert_equal 7, issue.fixed_version_id
387 end
387 end
388
388
389 def test_copy_to_the_same_project
389 def test_copy_to_the_same_project
390 issue = Issue.find(1)
390 issue = Issue.find(1)
391 copy = nil
391 copy = nil
392 assert_difference 'Issue.count' do
392 assert_difference 'Issue.count' do
393 copy = issue.move_to(issue.project, nil, :copy => true)
393 copy = issue.move_to(issue.project, nil, :copy => true)
394 end
394 end
395 assert_kind_of Issue, copy
395 assert_kind_of Issue, copy
396 assert_equal issue.project, copy.project
396 assert_equal issue.project, copy.project
397 assert_equal "125", copy.custom_value_for(2).value
397 assert_equal "125", copy.custom_value_for(2).value
398 end
398 end
399
399
400 def test_copy_to_another_project_and_tracker
400 def test_copy_to_another_project_and_tracker
401 issue = Issue.find(1)
401 issue = Issue.find(1)
402 copy = nil
402 copy = nil
403 assert_difference 'Issue.count' do
403 assert_difference 'Issue.count' do
404 copy = issue.move_to(Project.find(3), Tracker.find(2), :copy => true)
404 copy = issue.move_to(Project.find(3), Tracker.find(2), :copy => true)
405 end
405 end
406 assert_kind_of Issue, copy
406 assert_kind_of Issue, copy
407 assert_equal Project.find(3), copy.project
407 assert_equal Project.find(3), copy.project
408 assert_equal Tracker.find(2), copy.tracker
408 assert_equal Tracker.find(2), copy.tracker
409 # Custom field #2 is not associated with target tracker
409 # Custom field #2 is not associated with target tracker
410 assert_nil copy.custom_value_for(2)
410 assert_nil copy.custom_value_for(2)
411 end
411 end
412
412
413 context "#move_to" do
413 context "#move_to" do
414 context "as a copy" do
414 context "as a copy" do
415 setup do
415 setup do
416 @issue = Issue.find(1)
416 @issue = Issue.find(1)
417 @copy = nil
417 @copy = nil
418 end
418 end
419
419
420 should "allow assigned_to changes" do
420 should "allow assigned_to changes" do
421 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
421 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
422 assert_equal 3, @copy.assigned_to_id
422 assert_equal 3, @copy.assigned_to_id
423 end
423 end
424
424
425 should "allow status changes" do
425 should "allow status changes" do
426 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
426 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
427 assert_equal 2, @copy.status_id
427 assert_equal 2, @copy.status_id
428 end
428 end
429
429
430 should "allow start date changes" do
430 should "allow start date changes" do
431 date = Date.today
431 date = Date.today
432 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
432 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
433 assert_equal date, @copy.start_date
433 assert_equal date, @copy.start_date
434 end
434 end
435
435
436 should "allow due date changes" do
436 should "allow due date changes" do
437 date = Date.today
437 date = Date.today
438 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
438 @copy = @issue.move_to(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
439
439
440 assert_equal date, @copy.due_date
440 assert_equal date, @copy.due_date
441 end
441 end
442 end
442 end
443 end
443 end
444
444
445 def test_recipients_should_not_include_users_that_cannot_view_the_issue
445 def test_recipients_should_not_include_users_that_cannot_view_the_issue
446 issue = Issue.find(12)
446 issue = Issue.find(12)
447 assert issue.recipients.include?(issue.author.mail)
447 assert issue.recipients.include?(issue.author.mail)
448 # move the issue to a private project
448 # move the issue to a private project
449 copy = issue.move_to(Project.find(5), Tracker.find(2), :copy => true)
449 copy = issue.move_to(Project.find(5), Tracker.find(2), :copy => true)
450 # author is not a member of project anymore
450 # author is not a member of project anymore
451 assert !copy.recipients.include?(copy.author.mail)
451 assert !copy.recipients.include?(copy.author.mail)
452 end
452 end
453
453
454 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
454 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
455 user = User.find(3)
455 user = User.find(3)
456 issue = Issue.find(9)
456 issue = Issue.find(9)
457 Watcher.create!(:user => user, :watchable => issue)
457 Watcher.create!(:user => user, :watchable => issue)
458 assert issue.watched_by?(user)
458 assert issue.watched_by?(user)
459 assert !issue.watcher_recipients.include?(user.mail)
459 assert !issue.watcher_recipients.include?(user.mail)
460 end
460 end
461
461
462 def test_issue_destroy
462 def test_issue_destroy
463 Issue.find(1).destroy
463 Issue.find(1).destroy
464 assert_nil Issue.find_by_id(1)
464 assert_nil Issue.find_by_id(1)
465 assert_nil TimeEntry.find_by_issue_id(1)
465 assert_nil TimeEntry.find_by_issue_id(1)
466 end
466 end
467
467
468 def test_blocked
468 def test_blocked
469 blocked_issue = Issue.find(9)
469 blocked_issue = Issue.find(9)
470 blocking_issue = Issue.find(10)
470 blocking_issue = Issue.find(10)
471
471
472 assert blocked_issue.blocked?
472 assert blocked_issue.blocked?
473 assert !blocking_issue.blocked?
473 assert !blocking_issue.blocked?
474 end
474 end
475
475
476 def test_blocked_issues_dont_allow_closed_statuses
476 def test_blocked_issues_dont_allow_closed_statuses
477 blocked_issue = Issue.find(9)
477 blocked_issue = Issue.find(9)
478
478
479 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
479 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
480 assert !allowed_statuses.empty?
480 assert !allowed_statuses.empty?
481 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
481 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
482 assert closed_statuses.empty?
482 assert closed_statuses.empty?
483 end
483 end
484
484
485 def test_unblocked_issues_allow_closed_statuses
485 def test_unblocked_issues_allow_closed_statuses
486 blocking_issue = Issue.find(10)
486 blocking_issue = Issue.find(10)
487
487
488 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
488 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
489 assert !allowed_statuses.empty?
489 assert !allowed_statuses.empty?
490 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
490 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
491 assert !closed_statuses.empty?
491 assert !closed_statuses.empty?
492 end
492 end
493
493
494 def test_overdue
494 def test_overdue
495 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
495 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
496 assert !Issue.new(:due_date => Date.today).overdue?
496 assert !Issue.new(:due_date => Date.today).overdue?
497 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
497 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
498 assert !Issue.new(:due_date => nil).overdue?
498 assert !Issue.new(:due_date => nil).overdue?
499 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
499 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
500 end
500 end
501
501
502 def test_assignable_users
502 def test_assignable_users
503 assert_kind_of User, Issue.find(1).assignable_users.first
503 assert_kind_of User, Issue.find(1).assignable_users.first
504 end
504 end
505
505
506 def test_create_should_send_email_notification
506 def test_create_should_send_email_notification
507 ActionMailer::Base.deliveries.clear
507 ActionMailer::Base.deliveries.clear
508 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :estimated_hours => '1:30')
508 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'test_create', :estimated_hours => '1:30')
509
509
510 assert issue.save
510 assert issue.save
511 assert_equal 1, ActionMailer::Base.deliveries.size
511 assert_equal 1, ActionMailer::Base.deliveries.size
512 end
512 end
513
513
514 def test_stale_issue_should_not_send_email_notification
514 def test_stale_issue_should_not_send_email_notification
515 ActionMailer::Base.deliveries.clear
515 ActionMailer::Base.deliveries.clear
516 issue = Issue.find(1)
516 issue = Issue.find(1)
517 stale = Issue.find(1)
517 stale = Issue.find(1)
518
518
519 issue.init_journal(User.find(1))
519 issue.init_journal(User.find(1))
520 issue.subject = 'Subjet update'
520 issue.subject = 'Subjet update'
521 assert issue.save
521 assert issue.save
522 assert_equal 1, ActionMailer::Base.deliveries.size
522 assert_equal 1, ActionMailer::Base.deliveries.size
523 ActionMailer::Base.deliveries.clear
523 ActionMailer::Base.deliveries.clear
524
524
525 stale.init_journal(User.find(1))
525 stale.init_journal(User.find(1))
526 stale.subject = 'Another subjet update'
526 stale.subject = 'Another subjet update'
527 assert_raise ActiveRecord::StaleObjectError do
527 assert_raise ActiveRecord::StaleObjectError do
528 stale.save
528 stale.save
529 end
529 end
530 assert ActionMailer::Base.deliveries.empty?
530 assert ActionMailer::Base.deliveries.empty?
531 end
531 end
532
532
533 context "#done_ratio" do
533 context "#done_ratio" do
534 setup do
534 setup do
535 @issue = Issue.find(1)
535 @issue = Issue.find(1)
536 @issue_status = IssueStatus.find(1)
536 @issue_status = IssueStatus.find(1)
537 @issue_status.update_attribute(:default_done_ratio, 50)
537 @issue_status.update_attribute(:default_done_ratio, 50)
538 end
538 end
539
539
540 context "with Setting.issue_done_ratio using the issue_field" do
540 context "with Setting.issue_done_ratio using the issue_field" do
541 setup do
541 setup do
542 Setting.issue_done_ratio = 'issue_field'
542 Setting.issue_done_ratio = 'issue_field'
543 end
543 end
544
544
545 should "read the issue's field" do
545 should "read the issue's field" do
546 assert_equal 0, @issue.done_ratio
546 assert_equal 0, @issue.done_ratio
547 end
547 end
548 end
548 end
549
549
550 context "with Setting.issue_done_ratio using the issue_status" do
550 context "with Setting.issue_done_ratio using the issue_status" do
551 setup do
551 setup do
552 Setting.issue_done_ratio = 'issue_status'
552 Setting.issue_done_ratio = 'issue_status'
553 end
553 end
554
554
555 should "read the Issue Status's default done ratio" do
555 should "read the Issue Status's default done ratio" do
556 assert_equal 50, @issue.done_ratio
556 assert_equal 50, @issue.done_ratio
557 end
557 end
558 end
558 end
559 end
559 end
560
560
561 context "#update_done_ratio_from_issue_status" do
561 context "#update_done_ratio_from_issue_status" do
562 setup do
562 setup do
563 @issue = Issue.find(1)
563 @issue = Issue.find(1)
564 @issue_status = IssueStatus.find(1)
564 @issue_status = IssueStatus.find(1)
565 @issue_status.update_attribute(:default_done_ratio, 50)
565 @issue_status.update_attribute(:default_done_ratio, 50)
566 end
566 end
567
567
568 context "with Setting.issue_done_ratio using the issue_field" do
568 context "with Setting.issue_done_ratio using the issue_field" do
569 setup do
569 setup do
570 Setting.issue_done_ratio = 'issue_field'
570 Setting.issue_done_ratio = 'issue_field'
571 end
571 end
572
572
573 should "not change the issue" do
573 should "not change the issue" do
574 @issue.update_done_ratio_from_issue_status
574 @issue.update_done_ratio_from_issue_status
575
575
576 assert_equal 0, @issue.done_ratio
576 assert_equal 0, @issue.done_ratio
577 end
577 end
578 end
578 end
579
579
580 context "with Setting.issue_done_ratio using the issue_status" do
580 context "with Setting.issue_done_ratio using the issue_status" do
581 setup do
581 setup do
582 Setting.issue_done_ratio = 'issue_status'
582 Setting.issue_done_ratio = 'issue_status'
583 end
583 end
584
584
585 should "not change the issue's done ratio" do
585 should "not change the issue's done ratio" do
586 @issue.update_done_ratio_from_issue_status
586 @issue.update_done_ratio_from_issue_status
587
587
588 assert_equal 50, @issue.done_ratio
588 assert_equal 50, @issue.done_ratio
589 end
589 end
590 end
590 end
591 end
591 end
592
593 test "#by_tracker" do
594 groups = Issue.by_tracker(Project.find(1))
595 assert_equal 3, groups.size
596 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
597 end
598
599 test "#by_version" do
600 groups = Issue.by_version(Project.find(1))
601 assert_equal 3, groups.size
602 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
603 end
604
605 test "#by_priority" do
606 groups = Issue.by_priority(Project.find(1))
607 assert_equal 4, groups.size
608 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
609 end
610
611 test "#by_category" do
612 groups = Issue.by_category(Project.find(1))
613 assert_equal 2, groups.size
614 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
615 end
616
617 test "#by_assigned_to" do
618 groups = Issue.by_assigned_to(Project.find(1))
619 assert_equal 2, groups.size
620 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
621 end
622
623 test "#by_author" do
624 groups = Issue.by_author(Project.find(1))
625 assert_equal 4, groups.size
626 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
627 end
628
629 test "#by_subproject" do
630 groups = Issue.by_subproject(Project.find(1))
631 assert_equal 2, groups.size
632 assert_equal 5, groups.inject(0) {|sum, group| sum + group['total'].to_i}
633 end
592 end
634 end
General Comments 0
You need to be logged in to leave comments. Login now