##// END OF EJS Templates
Fixes strange random test failures with Mysql....
Jean-Philippe Lang -
r3610:edeb84a07052
parent child
Show More
@@ -1,1302 +1,1306
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 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 require 'issues_controller'
19 require 'issues_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class IssuesController; def rescue_action(e) raise e end; end
22 class IssuesController; def rescue_action(e) raise e end; end
23
23
24 class IssuesControllerTest < ActionController::TestCase
24 class IssuesControllerTest < ActionController::TestCase
25 fixtures :projects,
25 fixtures :projects,
26 :users,
26 :users,
27 :roles,
27 :roles,
28 :members,
28 :members,
29 :member_roles,
29 :member_roles,
30 :issues,
30 :issues,
31 :issue_statuses,
31 :issue_statuses,
32 :versions,
32 :versions,
33 :trackers,
33 :trackers,
34 :projects_trackers,
34 :projects_trackers,
35 :issue_categories,
35 :issue_categories,
36 :enabled_modules,
36 :enabled_modules,
37 :enumerations,
37 :enumerations,
38 :attachments,
38 :attachments,
39 :workflows,
39 :workflows,
40 :custom_fields,
40 :custom_fields,
41 :custom_values,
41 :custom_values,
42 :custom_fields_projects,
42 :custom_fields_projects,
43 :custom_fields_trackers,
43 :custom_fields_trackers,
44 :time_entries,
44 :time_entries,
45 :journals,
45 :journals,
46 :journal_details,
46 :journal_details,
47 :queries
47 :queries
48
48
49 def setup
49 def setup
50 @controller = IssuesController.new
50 @controller = IssuesController.new
51 @request = ActionController::TestRequest.new
51 @request = ActionController::TestRequest.new
52 @response = ActionController::TestResponse.new
52 @response = ActionController::TestResponse.new
53 User.current = nil
53 User.current = nil
54 end
54 end
55
55
56 def test_index
56 def test_index
57 Setting.default_language = 'en'
57 Setting.default_language = 'en'
58
58
59 get :index
59 get :index
60 assert_response :success
60 assert_response :success
61 assert_template 'index.rhtml'
61 assert_template 'index.rhtml'
62 assert_not_nil assigns(:issues)
62 assert_not_nil assigns(:issues)
63 assert_nil assigns(:project)
63 assert_nil assigns(:project)
64 assert_tag :tag => 'a', :content => /Can't print recipes/
64 assert_tag :tag => 'a', :content => /Can't print recipes/
65 assert_tag :tag => 'a', :content => /Subproject issue/
65 assert_tag :tag => 'a', :content => /Subproject issue/
66 # private projects hidden
66 # private projects hidden
67 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
67 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
68 assert_no_tag :tag => 'a', :content => /Issue on project 2/
68 assert_no_tag :tag => 'a', :content => /Issue on project 2/
69 # project column
69 # project column
70 assert_tag :tag => 'th', :content => /Project/
70 assert_tag :tag => 'th', :content => /Project/
71 end
71 end
72
72
73 def test_index_should_not_list_issues_when_module_disabled
73 def test_index_should_not_list_issues_when_module_disabled
74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
75 get :index
75 get :index
76 assert_response :success
76 assert_response :success
77 assert_template 'index.rhtml'
77 assert_template 'index.rhtml'
78 assert_not_nil assigns(:issues)
78 assert_not_nil assigns(:issues)
79 assert_nil assigns(:project)
79 assert_nil assigns(:project)
80 assert_no_tag :tag => 'a', :content => /Can't print recipes/
80 assert_no_tag :tag => 'a', :content => /Can't print recipes/
81 assert_tag :tag => 'a', :content => /Subproject issue/
81 assert_tag :tag => 'a', :content => /Subproject issue/
82 end
82 end
83
83
84 def test_index_should_not_list_issues_when_module_disabled
84 def test_index_should_not_list_issues_when_module_disabled
85 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
85 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
86 get :index
86 get :index
87 assert_response :success
87 assert_response :success
88 assert_template 'index.rhtml'
88 assert_template 'index.rhtml'
89 assert_not_nil assigns(:issues)
89 assert_not_nil assigns(:issues)
90 assert_nil assigns(:project)
90 assert_nil assigns(:project)
91 assert_no_tag :tag => 'a', :content => /Can't print recipes/
91 assert_no_tag :tag => 'a', :content => /Can't print recipes/
92 assert_tag :tag => 'a', :content => /Subproject issue/
92 assert_tag :tag => 'a', :content => /Subproject issue/
93 end
93 end
94
94
95 def test_index_with_project
95 def test_index_with_project
96 Setting.display_subprojects_issues = 0
96 Setting.display_subprojects_issues = 0
97 get :index, :project_id => 1
97 get :index, :project_id => 1
98 assert_response :success
98 assert_response :success
99 assert_template 'index.rhtml'
99 assert_template 'index.rhtml'
100 assert_not_nil assigns(:issues)
100 assert_not_nil assigns(:issues)
101 assert_tag :tag => 'a', :content => /Can't print recipes/
101 assert_tag :tag => 'a', :content => /Can't print recipes/
102 assert_no_tag :tag => 'a', :content => /Subproject issue/
102 assert_no_tag :tag => 'a', :content => /Subproject issue/
103 end
103 end
104
104
105 def test_index_with_project_and_subprojects
105 def test_index_with_project_and_subprojects
106 Setting.display_subprojects_issues = 1
106 Setting.display_subprojects_issues = 1
107 get :index, :project_id => 1
107 get :index, :project_id => 1
108 assert_response :success
108 assert_response :success
109 assert_template 'index.rhtml'
109 assert_template 'index.rhtml'
110 assert_not_nil assigns(:issues)
110 assert_not_nil assigns(:issues)
111 assert_tag :tag => 'a', :content => /Can't print recipes/
111 assert_tag :tag => 'a', :content => /Can't print recipes/
112 assert_tag :tag => 'a', :content => /Subproject issue/
112 assert_tag :tag => 'a', :content => /Subproject issue/
113 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
113 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
114 end
114 end
115
115
116 def test_index_with_project_and_subprojects_should_show_private_subprojects
116 def test_index_with_project_and_subprojects_should_show_private_subprojects
117 @request.session[:user_id] = 2
117 @request.session[:user_id] = 2
118 Setting.display_subprojects_issues = 1
118 Setting.display_subprojects_issues = 1
119 get :index, :project_id => 1
119 get :index, :project_id => 1
120 assert_response :success
120 assert_response :success
121 assert_template 'index.rhtml'
121 assert_template 'index.rhtml'
122 assert_not_nil assigns(:issues)
122 assert_not_nil assigns(:issues)
123 assert_tag :tag => 'a', :content => /Can't print recipes/
123 assert_tag :tag => 'a', :content => /Can't print recipes/
124 assert_tag :tag => 'a', :content => /Subproject issue/
124 assert_tag :tag => 'a', :content => /Subproject issue/
125 assert_tag :tag => 'a', :content => /Issue of a private subproject/
125 assert_tag :tag => 'a', :content => /Issue of a private subproject/
126 end
126 end
127
127
128 def test_index_with_project_and_filter
128 def test_index_with_project_and_filter
129 get :index, :project_id => 1, :set_filter => 1
129 get :index, :project_id => 1, :set_filter => 1
130 assert_response :success
130 assert_response :success
131 assert_template 'index.rhtml'
131 assert_template 'index.rhtml'
132 assert_not_nil assigns(:issues)
132 assert_not_nil assigns(:issues)
133 end
133 end
134
134
135 def test_index_with_query
135 def test_index_with_query
136 get :index, :project_id => 1, :query_id => 5
136 get :index, :project_id => 1, :query_id => 5
137 assert_response :success
137 assert_response :success
138 assert_template 'index.rhtml'
138 assert_template 'index.rhtml'
139 assert_not_nil assigns(:issues)
139 assert_not_nil assigns(:issues)
140 assert_nil assigns(:issue_count_by_group)
140 assert_nil assigns(:issue_count_by_group)
141 end
141 end
142
142
143 def test_index_with_query_grouped_by_tracker
143 def test_index_with_query_grouped_by_tracker
144 get :index, :project_id => 1, :query_id => 6
144 get :index, :project_id => 1, :query_id => 6
145 assert_response :success
145 assert_response :success
146 assert_template 'index.rhtml'
146 assert_template 'index.rhtml'
147 assert_not_nil assigns(:issues)
147 assert_not_nil assigns(:issues)
148 assert_not_nil assigns(:issue_count_by_group)
148 assert_not_nil assigns(:issue_count_by_group)
149 end
149 end
150
150
151 def test_index_with_query_grouped_by_list_custom_field
151 def test_index_with_query_grouped_by_list_custom_field
152 get :index, :project_id => 1, :query_id => 9
152 get :index, :project_id => 1, :query_id => 9
153 assert_response :success
153 assert_response :success
154 assert_template 'index.rhtml'
154 assert_template 'index.rhtml'
155 assert_not_nil assigns(:issues)
155 assert_not_nil assigns(:issues)
156 assert_not_nil assigns(:issue_count_by_group)
156 assert_not_nil assigns(:issue_count_by_group)
157 end
157 end
158
158
159 def test_index_sort_by_field_not_included_in_columns
159 def test_index_sort_by_field_not_included_in_columns
160 Setting.issue_list_default_columns = %w(subject author)
160 Setting.issue_list_default_columns = %w(subject author)
161 get :index, :sort => 'tracker'
161 get :index, :sort => 'tracker'
162 end
162 end
163
163
164 def test_index_csv_with_project
164 def test_index_csv_with_project
165 Setting.default_language = 'en'
165 Setting.default_language = 'en'
166
166
167 get :index, :format => 'csv'
167 get :index, :format => 'csv'
168 assert_response :success
168 assert_response :success
169 assert_not_nil assigns(:issues)
169 assert_not_nil assigns(:issues)
170 assert_equal 'text/csv', @response.content_type
170 assert_equal 'text/csv', @response.content_type
171 assert @response.body.starts_with?("#,")
171 assert @response.body.starts_with?("#,")
172
172
173 get :index, :project_id => 1, :format => 'csv'
173 get :index, :project_id => 1, :format => 'csv'
174 assert_response :success
174 assert_response :success
175 assert_not_nil assigns(:issues)
175 assert_not_nil assigns(:issues)
176 assert_equal 'text/csv', @response.content_type
176 assert_equal 'text/csv', @response.content_type
177 end
177 end
178
178
179 def test_index_pdf
179 def test_index_pdf
180 get :index, :format => 'pdf'
180 get :index, :format => 'pdf'
181 assert_response :success
181 assert_response :success
182 assert_not_nil assigns(:issues)
182 assert_not_nil assigns(:issues)
183 assert_equal 'application/pdf', @response.content_type
183 assert_equal 'application/pdf', @response.content_type
184
184
185 get :index, :project_id => 1, :format => 'pdf'
185 get :index, :project_id => 1, :format => 'pdf'
186 assert_response :success
186 assert_response :success
187 assert_not_nil assigns(:issues)
187 assert_not_nil assigns(:issues)
188 assert_equal 'application/pdf', @response.content_type
188 assert_equal 'application/pdf', @response.content_type
189
189
190 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
190 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
191 assert_response :success
191 assert_response :success
192 assert_not_nil assigns(:issues)
192 assert_not_nil assigns(:issues)
193 assert_equal 'application/pdf', @response.content_type
193 assert_equal 'application/pdf', @response.content_type
194 end
194 end
195
195
196 def test_index_pdf_with_query_grouped_by_list_custom_field
196 def test_index_pdf_with_query_grouped_by_list_custom_field
197 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
197 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
198 assert_response :success
198 assert_response :success
199 assert_not_nil assigns(:issues)
199 assert_not_nil assigns(:issues)
200 assert_not_nil assigns(:issue_count_by_group)
200 assert_not_nil assigns(:issue_count_by_group)
201 assert_equal 'application/pdf', @response.content_type
201 assert_equal 'application/pdf', @response.content_type
202 end
202 end
203
203
204 def test_index_sort
204 def test_index_sort
205 get :index, :sort => 'tracker,id:desc'
205 get :index, :sort => 'tracker,id:desc'
206 assert_response :success
206 assert_response :success
207
207
208 sort_params = @request.session['issues_index_sort']
208 sort_params = @request.session['issues_index_sort']
209 assert sort_params.is_a?(String)
209 assert sort_params.is_a?(String)
210 assert_equal 'tracker,id:desc', sort_params
210 assert_equal 'tracker,id:desc', sort_params
211
211
212 issues = assigns(:issues)
212 issues = assigns(:issues)
213 assert_not_nil issues
213 assert_not_nil issues
214 assert !issues.empty?
214 assert !issues.empty?
215 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
215 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
216 end
216 end
217
217
218 def test_index_with_columns
218 def test_index_with_columns
219 columns = ['tracker', 'subject', 'assigned_to']
219 columns = ['tracker', 'subject', 'assigned_to']
220 get :index, :set_filter => 1, :query => { 'column_names' => columns}
220 get :index, :set_filter => 1, :query => { 'column_names' => columns}
221 assert_response :success
221 assert_response :success
222
222
223 # query should use specified columns
223 # query should use specified columns
224 query = assigns(:query)
224 query = assigns(:query)
225 assert_kind_of Query, query
225 assert_kind_of Query, query
226 assert_equal columns, query.column_names.map(&:to_s)
226 assert_equal columns, query.column_names.map(&:to_s)
227
227
228 # columns should be stored in session
228 # columns should be stored in session
229 assert_kind_of Hash, session[:query]
229 assert_kind_of Hash, session[:query]
230 assert_kind_of Array, session[:query][:column_names]
230 assert_kind_of Array, session[:query][:column_names]
231 assert_equal columns, session[:query][:column_names].map(&:to_s)
231 assert_equal columns, session[:query][:column_names].map(&:to_s)
232 end
232 end
233
233
234 def test_calendar
234 def test_calendar
235 get :calendar, :project_id => 1
235 get :calendar, :project_id => 1
236 assert_response :success
236 assert_response :success
237 assert_template 'calendar'
237 assert_template 'calendar'
238 assert_not_nil assigns(:calendar)
238 assert_not_nil assigns(:calendar)
239 end
239 end
240
240
241 def test_cross_project_calendar
241 def test_cross_project_calendar
242 get :calendar
242 get :calendar
243 assert_response :success
243 assert_response :success
244 assert_template 'calendar'
244 assert_template 'calendar'
245 assert_not_nil assigns(:calendar)
245 assert_not_nil assigns(:calendar)
246 end
246 end
247
247
248 def test_changes
248 def test_changes
249 get :changes, :project_id => 1
249 get :changes, :project_id => 1
250 assert_response :success
250 assert_response :success
251 assert_not_nil assigns(:journals)
251 assert_not_nil assigns(:journals)
252 assert_equal 'application/atom+xml', @response.content_type
252 assert_equal 'application/atom+xml', @response.content_type
253 end
253 end
254
254
255 def test_show_by_anonymous
255 def test_show_by_anonymous
256 get :show, :id => 1
256 get :show, :id => 1
257 assert_response :success
257 assert_response :success
258 assert_template 'show.rhtml'
258 assert_template 'show.rhtml'
259 assert_not_nil assigns(:issue)
259 assert_not_nil assigns(:issue)
260 assert_equal Issue.find(1), assigns(:issue)
260 assert_equal Issue.find(1), assigns(:issue)
261
261
262 # anonymous role is allowed to add a note
262 # anonymous role is allowed to add a note
263 assert_tag :tag => 'form',
263 assert_tag :tag => 'form',
264 :descendant => { :tag => 'fieldset',
264 :descendant => { :tag => 'fieldset',
265 :child => { :tag => 'legend',
265 :child => { :tag => 'legend',
266 :content => /Notes/ } }
266 :content => /Notes/ } }
267 end
267 end
268
268
269 def test_show_by_manager
269 def test_show_by_manager
270 @request.session[:user_id] = 2
270 @request.session[:user_id] = 2
271 get :show, :id => 1
271 get :show, :id => 1
272 assert_response :success
272 assert_response :success
273
273
274 assert_tag :tag => 'form',
274 assert_tag :tag => 'form',
275 :descendant => { :tag => 'fieldset',
275 :descendant => { :tag => 'fieldset',
276 :child => { :tag => 'legend',
276 :child => { :tag => 'legend',
277 :content => /Change properties/ } },
277 :content => /Change properties/ } },
278 :descendant => { :tag => 'fieldset',
278 :descendant => { :tag => 'fieldset',
279 :child => { :tag => 'legend',
279 :child => { :tag => 'legend',
280 :content => /Log time/ } },
280 :content => /Log time/ } },
281 :descendant => { :tag => 'fieldset',
281 :descendant => { :tag => 'fieldset',
282 :child => { :tag => 'legend',
282 :child => { :tag => 'legend',
283 :content => /Notes/ } }
283 :content => /Notes/ } }
284 end
284 end
285
285
286 def test_show_should_deny_anonymous_access_without_permission
286 def test_show_should_deny_anonymous_access_without_permission
287 Role.anonymous.remove_permission!(:view_issues)
287 Role.anonymous.remove_permission!(:view_issues)
288 get :show, :id => 1
288 get :show, :id => 1
289 assert_response :redirect
289 assert_response :redirect
290 end
290 end
291
291
292 def test_show_should_deny_non_member_access_without_permission
292 def test_show_should_deny_non_member_access_without_permission
293 Role.non_member.remove_permission!(:view_issues)
293 Role.non_member.remove_permission!(:view_issues)
294 @request.session[:user_id] = 9
294 @request.session[:user_id] = 9
295 get :show, :id => 1
295 get :show, :id => 1
296 assert_response 403
296 assert_response 403
297 end
297 end
298
298
299 def test_show_should_deny_member_access_without_permission
299 def test_show_should_deny_member_access_without_permission
300 Role.find(1).remove_permission!(:view_issues)
300 Role.find(1).remove_permission!(:view_issues)
301 @request.session[:user_id] = 2
301 @request.session[:user_id] = 2
302 get :show, :id => 1
302 get :show, :id => 1
303 assert_response 403
303 assert_response 403
304 end
304 end
305
305
306 def test_show_should_not_disclose_relations_to_invisible_issues
306 def test_show_should_not_disclose_relations_to_invisible_issues
307 Setting.cross_project_issue_relations = '1'
307 Setting.cross_project_issue_relations = '1'
308 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
308 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
309 # Relation to a private project issue
309 # Relation to a private project issue
310 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
310 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
311
311
312 get :show, :id => 1
312 get :show, :id => 1
313 assert_response :success
313 assert_response :success
314
314
315 assert_tag :div, :attributes => { :id => 'relations' },
315 assert_tag :div, :attributes => { :id => 'relations' },
316 :descendant => { :tag => 'a', :content => /#2$/ }
316 :descendant => { :tag => 'a', :content => /#2$/ }
317 assert_no_tag :div, :attributes => { :id => 'relations' },
317 assert_no_tag :div, :attributes => { :id => 'relations' },
318 :descendant => { :tag => 'a', :content => /#4$/ }
318 :descendant => { :tag => 'a', :content => /#4$/ }
319 end
319 end
320
320
321 def test_show_atom
321 def test_show_atom
322 get :show, :id => 2, :format => 'atom'
322 get :show, :id => 2, :format => 'atom'
323 assert_response :success
323 assert_response :success
324 assert_template 'changes.rxml'
324 assert_template 'changes.rxml'
325 # Inline image
325 # Inline image
326 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
326 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
327 end
327 end
328
328
329 def test_show_export_to_pdf
329 def test_show_export_to_pdf
330 get :show, :id => 3, :format => 'pdf'
330 get :show, :id => 3, :format => 'pdf'
331 assert_response :success
331 assert_response :success
332 assert_equal 'application/pdf', @response.content_type
332 assert_equal 'application/pdf', @response.content_type
333 assert @response.body.starts_with?('%PDF')
333 assert @response.body.starts_with?('%PDF')
334 assert_not_nil assigns(:issue)
334 assert_not_nil assigns(:issue)
335 end
335 end
336
336
337 def test_get_new
337 def test_get_new
338 @request.session[:user_id] = 2
338 @request.session[:user_id] = 2
339 get :new, :project_id => 1, :tracker_id => 1
339 get :new, :project_id => 1, :tracker_id => 1
340 assert_response :success
340 assert_response :success
341 assert_template 'new'
341 assert_template 'new'
342
342
343 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
343 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
344 :value => 'Default string' }
344 :value => 'Default string' }
345 end
345 end
346
346
347 def test_get_new_without_tracker_id
347 def test_get_new_without_tracker_id
348 @request.session[:user_id] = 2
348 @request.session[:user_id] = 2
349 get :new, :project_id => 1
349 get :new, :project_id => 1
350 assert_response :success
350 assert_response :success
351 assert_template 'new'
351 assert_template 'new'
352
352
353 issue = assigns(:issue)
353 issue = assigns(:issue)
354 assert_not_nil issue
354 assert_not_nil issue
355 assert_equal Project.find(1).trackers.first, issue.tracker
355 assert_equal Project.find(1).trackers.first, issue.tracker
356 end
356 end
357
357
358 def test_get_new_with_no_default_status_should_display_an_error
358 def test_get_new_with_no_default_status_should_display_an_error
359 @request.session[:user_id] = 2
359 @request.session[:user_id] = 2
360 IssueStatus.delete_all
360 IssueStatus.delete_all
361
361
362 get :new, :project_id => 1
362 get :new, :project_id => 1
363 assert_response 500
363 assert_response 500
364 assert_not_nil flash[:error]
364 assert_not_nil flash[:error]
365 assert_tag :tag => 'div', :attributes => { :class => /error/ },
365 assert_tag :tag => 'div', :attributes => { :class => /error/ },
366 :content => /No default issue/
366 :content => /No default issue/
367 end
367 end
368
368
369 def test_get_new_with_no_tracker_should_display_an_error
369 def test_get_new_with_no_tracker_should_display_an_error
370 @request.session[:user_id] = 2
370 @request.session[:user_id] = 2
371 Tracker.delete_all
371 Tracker.delete_all
372
372
373 get :new, :project_id => 1
373 get :new, :project_id => 1
374 assert_response 500
374 assert_response 500
375 assert_not_nil flash[:error]
375 assert_not_nil flash[:error]
376 assert_tag :tag => 'div', :attributes => { :class => /error/ },
376 assert_tag :tag => 'div', :attributes => { :class => /error/ },
377 :content => /No tracker/
377 :content => /No tracker/
378 end
378 end
379
379
380 def test_update_new_form
380 def test_update_new_form
381 @request.session[:user_id] = 2
381 @request.session[:user_id] = 2
382 xhr :post, :update_form, :project_id => 1,
382 xhr :post, :update_form, :project_id => 1,
383 :issue => {:tracker_id => 2,
383 :issue => {:tracker_id => 2,
384 :subject => 'This is the test_new issue',
384 :subject => 'This is the test_new issue',
385 :description => 'This is the description',
385 :description => 'This is the description',
386 :priority_id => 5}
386 :priority_id => 5}
387 assert_response :success
387 assert_response :success
388 assert_template 'attributes'
388 assert_template 'attributes'
389
389
390 issue = assigns(:issue)
390 issue = assigns(:issue)
391 assert_kind_of Issue, issue
391 assert_kind_of Issue, issue
392 assert_equal 1, issue.project_id
392 assert_equal 1, issue.project_id
393 assert_equal 2, issue.tracker_id
393 assert_equal 2, issue.tracker_id
394 assert_equal 'This is the test_new issue', issue.subject
394 assert_equal 'This is the test_new issue', issue.subject
395 end
395 end
396
396
397 def test_post_create
397 def test_post_create
398 @request.session[:user_id] = 2
398 @request.session[:user_id] = 2
399 assert_difference 'Issue.count' do
399 assert_difference 'Issue.count' do
400 post :create, :project_id => 1,
400 post :create, :project_id => 1,
401 :issue => {:tracker_id => 3,
401 :issue => {:tracker_id => 3,
402 :status_id => 2,
402 :status_id => 2,
403 :subject => 'This is the test_new issue',
403 :subject => 'This is the test_new issue',
404 :description => 'This is the description',
404 :description => 'This is the description',
405 :priority_id => 5,
405 :priority_id => 5,
406 :estimated_hours => '',
406 :estimated_hours => '',
407 :custom_field_values => {'2' => 'Value for field 2'}}
407 :custom_field_values => {'2' => 'Value for field 2'}}
408 end
408 end
409 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
409 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
410
410
411 issue = Issue.find_by_subject('This is the test_new issue')
411 issue = Issue.find_by_subject('This is the test_new issue')
412 assert_not_nil issue
412 assert_not_nil issue
413 assert_equal 2, issue.author_id
413 assert_equal 2, issue.author_id
414 assert_equal 3, issue.tracker_id
414 assert_equal 3, issue.tracker_id
415 assert_equal 2, issue.status_id
415 assert_equal 2, issue.status_id
416 assert_nil issue.estimated_hours
416 assert_nil issue.estimated_hours
417 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
417 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
418 assert_not_nil v
418 assert_not_nil v
419 assert_equal 'Value for field 2', v.value
419 assert_equal 'Value for field 2', v.value
420 end
420 end
421
421
422 def test_post_create_and_continue
422 def test_post_create_and_continue
423 @request.session[:user_id] = 2
423 @request.session[:user_id] = 2
424 post :create, :project_id => 1,
424 post :create, :project_id => 1,
425 :issue => {:tracker_id => 3,
425 :issue => {:tracker_id => 3,
426 :subject => 'This is first issue',
426 :subject => 'This is first issue',
427 :priority_id => 5},
427 :priority_id => 5},
428 :continue => ''
428 :continue => ''
429 assert_redirected_to :controller => 'issues', :action => 'new', :issue => {:tracker_id => 3}
429 assert_redirected_to :controller => 'issues', :action => 'new', :issue => {:tracker_id => 3}
430 end
430 end
431
431
432 def test_post_create_without_custom_fields_param
432 def test_post_create_without_custom_fields_param
433 @request.session[:user_id] = 2
433 @request.session[:user_id] = 2
434 assert_difference 'Issue.count' do
434 assert_difference 'Issue.count' do
435 post :create, :project_id => 1,
435 post :create, :project_id => 1,
436 :issue => {:tracker_id => 1,
436 :issue => {:tracker_id => 1,
437 :subject => 'This is the test_new issue',
437 :subject => 'This is the test_new issue',
438 :description => 'This is the description',
438 :description => 'This is the description',
439 :priority_id => 5}
439 :priority_id => 5}
440 end
440 end
441 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
441 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
442 end
442 end
443
443
444 def test_post_create_with_required_custom_field_and_without_custom_fields_param
444 def test_post_create_with_required_custom_field_and_without_custom_fields_param
445 field = IssueCustomField.find_by_name('Database')
445 field = IssueCustomField.find_by_name('Database')
446 field.update_attribute(:is_required, true)
446 field.update_attribute(:is_required, true)
447
447
448 @request.session[:user_id] = 2
448 @request.session[:user_id] = 2
449 post :create, :project_id => 1,
449 post :create, :project_id => 1,
450 :issue => {:tracker_id => 1,
450 :issue => {:tracker_id => 1,
451 :subject => 'This is the test_new issue',
451 :subject => 'This is the test_new issue',
452 :description => 'This is the description',
452 :description => 'This is the description',
453 :priority_id => 5}
453 :priority_id => 5}
454 assert_response :success
454 assert_response :success
455 assert_template 'new'
455 assert_template 'new'
456 issue = assigns(:issue)
456 issue = assigns(:issue)
457 assert_not_nil issue
457 assert_not_nil issue
458 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
458 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
459 end
459 end
460
460
461 def test_post_create_with_watchers
461 def test_post_create_with_watchers
462 @request.session[:user_id] = 2
462 @request.session[:user_id] = 2
463 ActionMailer::Base.deliveries.clear
463 ActionMailer::Base.deliveries.clear
464
464
465 assert_difference 'Watcher.count', 2 do
465 assert_difference 'Watcher.count', 2 do
466 post :create, :project_id => 1,
466 post :create, :project_id => 1,
467 :issue => {:tracker_id => 1,
467 :issue => {:tracker_id => 1,
468 :subject => 'This is a new issue with watchers',
468 :subject => 'This is a new issue with watchers',
469 :description => 'This is the description',
469 :description => 'This is the description',
470 :priority_id => 5,
470 :priority_id => 5,
471 :watcher_user_ids => ['2', '3']}
471 :watcher_user_ids => ['2', '3']}
472 end
472 end
473 issue = Issue.find_by_subject('This is a new issue with watchers')
473 issue = Issue.find_by_subject('This is a new issue with watchers')
474 assert_not_nil issue
474 assert_not_nil issue
475 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
475 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
476
476
477 # Watchers added
477 # Watchers added
478 assert_equal [2, 3], issue.watcher_user_ids.sort
478 assert_equal [2, 3], issue.watcher_user_ids.sort
479 assert issue.watched_by?(User.find(3))
479 assert issue.watched_by?(User.find(3))
480 # Watchers notified
480 # Watchers notified
481 mail = ActionMailer::Base.deliveries.last
481 mail = ActionMailer::Base.deliveries.last
482 assert_kind_of TMail::Mail, mail
482 assert_kind_of TMail::Mail, mail
483 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
483 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
484 end
484 end
485
485
486 def test_post_create_subissue
486 def test_post_create_subissue
487 @request.session[:user_id] = 2
487 @request.session[:user_id] = 2
488
488
489 assert_difference 'Issue.count' do
489 assert_difference 'Issue.count' do
490 post :create, :project_id => 1,
490 post :create, :project_id => 1,
491 :issue => {:tracker_id => 1,
491 :issue => {:tracker_id => 1,
492 :subject => 'This is a child issue',
492 :subject => 'This is a child issue',
493 :parent_issue_id => 2}
493 :parent_issue_id => 2}
494 end
494 end
495 issue = Issue.find_by_subject('This is a child issue')
495 issue = Issue.find_by_subject('This is a child issue')
496 assert_not_nil issue
496 assert_not_nil issue
497 assert_equal Issue.find(2), issue.parent
497 assert_equal Issue.find(2), issue.parent
498 end
498 end
499
499
500 def test_post_create_should_send_a_notification
500 def test_post_create_should_send_a_notification
501 ActionMailer::Base.deliveries.clear
501 ActionMailer::Base.deliveries.clear
502 @request.session[:user_id] = 2
502 @request.session[:user_id] = 2
503 assert_difference 'Issue.count' do
503 assert_difference 'Issue.count' do
504 post :create, :project_id => 1,
504 post :create, :project_id => 1,
505 :issue => {:tracker_id => 3,
505 :issue => {:tracker_id => 3,
506 :subject => 'This is the test_new issue',
506 :subject => 'This is the test_new issue',
507 :description => 'This is the description',
507 :description => 'This is the description',
508 :priority_id => 5,
508 :priority_id => 5,
509 :estimated_hours => '',
509 :estimated_hours => '',
510 :custom_field_values => {'2' => 'Value for field 2'}}
510 :custom_field_values => {'2' => 'Value for field 2'}}
511 end
511 end
512 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
512 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
513
513
514 assert_equal 1, ActionMailer::Base.deliveries.size
514 assert_equal 1, ActionMailer::Base.deliveries.size
515 end
515 end
516
516
517 def test_post_create_should_preserve_fields_values_on_validation_failure
517 def test_post_create_should_preserve_fields_values_on_validation_failure
518 @request.session[:user_id] = 2
518 @request.session[:user_id] = 2
519 post :create, :project_id => 1,
519 post :create, :project_id => 1,
520 :issue => {:tracker_id => 1,
520 :issue => {:tracker_id => 1,
521 # empty subject
521 # empty subject
522 :subject => '',
522 :subject => '',
523 :description => 'This is a description',
523 :description => 'This is a description',
524 :priority_id => 6,
524 :priority_id => 6,
525 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
525 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
526 assert_response :success
526 assert_response :success
527 assert_template 'new'
527 assert_template 'new'
528
528
529 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
529 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
530 :content => 'This is a description'
530 :content => 'This is a description'
531 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
531 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
532 :child => { :tag => 'option', :attributes => { :selected => 'selected',
532 :child => { :tag => 'option', :attributes => { :selected => 'selected',
533 :value => '6' },
533 :value => '6' },
534 :content => 'High' }
534 :content => 'High' }
535 # Custom fields
535 # Custom fields
536 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
536 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
537 :child => { :tag => 'option', :attributes => { :selected => 'selected',
537 :child => { :tag => 'option', :attributes => { :selected => 'selected',
538 :value => 'Oracle' },
538 :value => 'Oracle' },
539 :content => 'Oracle' }
539 :content => 'Oracle' }
540 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
540 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
541 :value => 'Value for field 2'}
541 :value => 'Value for field 2'}
542 end
542 end
543
543
544 def test_post_create_should_ignore_non_safe_attributes
544 def test_post_create_should_ignore_non_safe_attributes
545 @request.session[:user_id] = 2
545 @request.session[:user_id] = 2
546 assert_nothing_raised do
546 assert_nothing_raised do
547 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
547 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
548 end
548 end
549 end
549 end
550
550
551 context "without workflow privilege" do
551 context "without workflow privilege" do
552 setup do
552 setup do
553 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
553 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
554 Role.anonymous.add_permission! :add_issues
554 Role.anonymous.add_permission! :add_issues
555 end
555 end
556
556
557 context "#new" do
557 context "#new" do
558 should "propose default status only" do
558 should "propose default status only" do
559 get :new, :project_id => 1
559 get :new, :project_id => 1
560 assert_response :success
560 assert_response :success
561 assert_template 'new'
561 assert_template 'new'
562 assert_tag :tag => 'select',
562 assert_tag :tag => 'select',
563 :attributes => {:name => 'issue[status_id]'},
563 :attributes => {:name => 'issue[status_id]'},
564 :children => {:count => 1},
564 :children => {:count => 1},
565 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
565 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
566 end
566 end
567
567
568 should "accept default status" do
568 should "accept default status" do
569 assert_difference 'Issue.count' do
569 assert_difference 'Issue.count' do
570 post :create, :project_id => 1,
570 post :create, :project_id => 1,
571 :issue => {:tracker_id => 1,
571 :issue => {:tracker_id => 1,
572 :subject => 'This is an issue',
572 :subject => 'This is an issue',
573 :status_id => 1}
573 :status_id => 1}
574 end
574 end
575 issue = Issue.last(:order => 'id')
575 issue = Issue.last(:order => 'id')
576 assert_equal IssueStatus.default, issue.status
576 assert_equal IssueStatus.default, issue.status
577 end
577 end
578
578
579 should "ignore unauthorized status" do
579 should "ignore unauthorized status" do
580 assert_difference 'Issue.count' do
580 assert_difference 'Issue.count' do
581 post :create, :project_id => 1,
581 post :create, :project_id => 1,
582 :issue => {:tracker_id => 1,
582 :issue => {:tracker_id => 1,
583 :subject => 'This is an issue',
583 :subject => 'This is an issue',
584 :status_id => 3}
584 :status_id => 3}
585 end
585 end
586 issue = Issue.last(:order => 'id')
586 issue = Issue.last(:order => 'id')
587 assert_equal IssueStatus.default, issue.status
587 assert_equal IssueStatus.default, issue.status
588 end
588 end
589 end
589 end
590 end
590 end
591
591
592 def test_copy_issue
592 def test_copy_issue
593 @request.session[:user_id] = 2
593 @request.session[:user_id] = 2
594 get :new, :project_id => 1, :copy_from => 1
594 get :new, :project_id => 1, :copy_from => 1
595 assert_template 'new'
595 assert_template 'new'
596 assert_not_nil assigns(:issue)
596 assert_not_nil assigns(:issue)
597 orig = Issue.find(1)
597 orig = Issue.find(1)
598 assert_equal orig.subject, assigns(:issue).subject
598 assert_equal orig.subject, assigns(:issue).subject
599 end
599 end
600
600
601 def test_get_edit
601 def test_get_edit
602 @request.session[:user_id] = 2
602 @request.session[:user_id] = 2
603 get :edit, :id => 1
603 get :edit, :id => 1
604 assert_response :success
604 assert_response :success
605 assert_template 'edit'
605 assert_template 'edit'
606 assert_not_nil assigns(:issue)
606 assert_not_nil assigns(:issue)
607 assert_equal Issue.find(1), assigns(:issue)
607 assert_equal Issue.find(1), assigns(:issue)
608 end
608 end
609
609
610 def test_get_edit_with_params
610 def test_get_edit_with_params
611 @request.session[:user_id] = 2
611 @request.session[:user_id] = 2
612 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
612 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
613 assert_response :success
613 assert_response :success
614 assert_template 'edit'
614 assert_template 'edit'
615
615
616 issue = assigns(:issue)
616 issue = assigns(:issue)
617 assert_not_nil issue
617 assert_not_nil issue
618
618
619 assert_equal 5, issue.status_id
619 assert_equal 5, issue.status_id
620 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
620 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
621 :child => { :tag => 'option',
621 :child => { :tag => 'option',
622 :content => 'Closed',
622 :content => 'Closed',
623 :attributes => { :selected => 'selected' } }
623 :attributes => { :selected => 'selected' } }
624
624
625 assert_equal 7, issue.priority_id
625 assert_equal 7, issue.priority_id
626 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
626 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
627 :child => { :tag => 'option',
627 :child => { :tag => 'option',
628 :content => 'Urgent',
628 :content => 'Urgent',
629 :attributes => { :selected => 'selected' } }
629 :attributes => { :selected => 'selected' } }
630 end
630 end
631
631
632 def test_update_edit_form
632 def test_update_edit_form
633 @request.session[:user_id] = 2
633 @request.session[:user_id] = 2
634 xhr :post, :update_form, :project_id => 1,
634 xhr :post, :update_form, :project_id => 1,
635 :id => 1,
635 :id => 1,
636 :issue => {:tracker_id => 2,
636 :issue => {:tracker_id => 2,
637 :subject => 'This is the test_new issue',
637 :subject => 'This is the test_new issue',
638 :description => 'This is the description',
638 :description => 'This is the description',
639 :priority_id => 5}
639 :priority_id => 5}
640 assert_response :success
640 assert_response :success
641 assert_template 'attributes'
641 assert_template 'attributes'
642
642
643 issue = assigns(:issue)
643 issue = assigns(:issue)
644 assert_kind_of Issue, issue
644 assert_kind_of Issue, issue
645 assert_equal 1, issue.id
645 assert_equal 1, issue.id
646 assert_equal 1, issue.project_id
646 assert_equal 1, issue.project_id
647 assert_equal 2, issue.tracker_id
647 assert_equal 2, issue.tracker_id
648 assert_equal 'This is the test_new issue', issue.subject
648 assert_equal 'This is the test_new issue', issue.subject
649 end
649 end
650
650
651 def test_reply_to_issue
651 def test_reply_to_issue
652 @request.session[:user_id] = 2
652 @request.session[:user_id] = 2
653 get :reply, :id => 1
653 get :reply, :id => 1
654 assert_response :success
654 assert_response :success
655 assert_select_rjs :show, "update"
655 assert_select_rjs :show, "update"
656 end
656 end
657
657
658 def test_reply_to_note
658 def test_reply_to_note
659 @request.session[:user_id] = 2
659 @request.session[:user_id] = 2
660 get :reply, :id => 1, :journal_id => 2
660 get :reply, :id => 1, :journal_id => 2
661 assert_response :success
661 assert_response :success
662 assert_select_rjs :show, "update"
662 assert_select_rjs :show, "update"
663 end
663 end
664
664
665 def test_update_using_invalid_http_verbs
665 def test_update_using_invalid_http_verbs
666 @request.session[:user_id] = 2
666 @request.session[:user_id] = 2
667 subject = 'Updated by an invalid http verb'
667 subject = 'Updated by an invalid http verb'
668
668
669 get :update, :id => 1, :issue => {:subject => subject}
669 get :update, :id => 1, :issue => {:subject => subject}
670 assert_not_equal subject, Issue.find(1).subject
670 assert_not_equal subject, Issue.find(1).subject
671
671
672 post :update, :id => 1, :issue => {:subject => subject}
672 post :update, :id => 1, :issue => {:subject => subject}
673 assert_not_equal subject, Issue.find(1).subject
673 assert_not_equal subject, Issue.find(1).subject
674
674
675 delete :update, :id => 1, :issue => {:subject => subject}
675 delete :update, :id => 1, :issue => {:subject => subject}
676 assert_not_equal subject, Issue.find(1).subject
676 assert_not_equal subject, Issue.find(1).subject
677 end
677 end
678
678
679 def test_put_update_without_custom_fields_param
679 def test_put_update_without_custom_fields_param
680 @request.session[:user_id] = 2
680 @request.session[:user_id] = 2
681 ActionMailer::Base.deliveries.clear
681 ActionMailer::Base.deliveries.clear
682
682
683 issue = Issue.find(1)
683 issue = Issue.find(1)
684 assert_equal '125', issue.custom_value_for(2).value
684 assert_equal '125', issue.custom_value_for(2).value
685 old_subject = issue.subject
685 old_subject = issue.subject
686 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
686 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
687
687
688 assert_difference('Journal.count') do
688 assert_difference('Journal.count') do
689 assert_difference('JournalDetail.count', 2) do
689 assert_difference('JournalDetail.count', 2) do
690 put :update, :id => 1, :issue => {:subject => new_subject,
690 put :update, :id => 1, :issue => {:subject => new_subject,
691 :priority_id => '6',
691 :priority_id => '6',
692 :category_id => '1' # no change
692 :category_id => '1' # no change
693 }
693 }
694 end
694 end
695 end
695 end
696 assert_redirected_to :action => 'show', :id => '1'
696 assert_redirected_to :action => 'show', :id => '1'
697 issue.reload
697 issue.reload
698 assert_equal new_subject, issue.subject
698 assert_equal new_subject, issue.subject
699 # Make sure custom fields were not cleared
699 # Make sure custom fields were not cleared
700 assert_equal '125', issue.custom_value_for(2).value
700 assert_equal '125', issue.custom_value_for(2).value
701
701
702 mail = ActionMailer::Base.deliveries.last
702 mail = ActionMailer::Base.deliveries.last
703 assert_kind_of TMail::Mail, mail
703 assert_kind_of TMail::Mail, mail
704 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
704 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
705 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
705 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
706 end
706 end
707
707
708 def test_put_update_with_custom_field_change
708 def test_put_update_with_custom_field_change
709 @request.session[:user_id] = 2
709 @request.session[:user_id] = 2
710 issue = Issue.find(1)
710 issue = Issue.find(1)
711 assert_equal '125', issue.custom_value_for(2).value
711 assert_equal '125', issue.custom_value_for(2).value
712
712
713 assert_difference('Journal.count') do
713 assert_difference('Journal.count') do
714 assert_difference('JournalDetail.count', 3) do
714 assert_difference('JournalDetail.count', 3) do
715 put :update, :id => 1, :issue => {:subject => 'Custom field change',
715 put :update, :id => 1, :issue => {:subject => 'Custom field change',
716 :priority_id => '6',
716 :priority_id => '6',
717 :category_id => '1', # no change
717 :category_id => '1', # no change
718 :custom_field_values => { '2' => 'New custom value' }
718 :custom_field_values => { '2' => 'New custom value' }
719 }
719 }
720 end
720 end
721 end
721 end
722 assert_redirected_to :action => 'show', :id => '1'
722 assert_redirected_to :action => 'show', :id => '1'
723 issue.reload
723 issue.reload
724 assert_equal 'New custom value', issue.custom_value_for(2).value
724 assert_equal 'New custom value', issue.custom_value_for(2).value
725
725
726 mail = ActionMailer::Base.deliveries.last
726 mail = ActionMailer::Base.deliveries.last
727 assert_kind_of TMail::Mail, mail
727 assert_kind_of TMail::Mail, mail
728 assert mail.body.include?("Searchable field changed from 125 to New custom value")
728 assert mail.body.include?("Searchable field changed from 125 to New custom value")
729 end
729 end
730
730
731 def test_put_update_with_status_and_assignee_change
731 def test_put_update_with_status_and_assignee_change
732 issue = Issue.find(1)
732 issue = Issue.find(1)
733 assert_equal 1, issue.status_id
733 assert_equal 1, issue.status_id
734 @request.session[:user_id] = 2
734 @request.session[:user_id] = 2
735 assert_difference('TimeEntry.count', 0) do
735 assert_difference('TimeEntry.count', 0) do
736 put :update,
736 put :update,
737 :id => 1,
737 :id => 1,
738 :issue => { :status_id => 2, :assigned_to_id => 3 },
738 :issue => { :status_id => 2, :assigned_to_id => 3 },
739 :notes => 'Assigned to dlopper',
739 :notes => 'Assigned to dlopper',
740 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
740 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
741 end
741 end
742 assert_redirected_to :action => 'show', :id => '1'
742 assert_redirected_to :action => 'show', :id => '1'
743 issue.reload
743 issue.reload
744 assert_equal 2, issue.status_id
744 assert_equal 2, issue.status_id
745 j = Journal.find(:first, :order => 'id DESC')
745 j = Journal.find(:first, :order => 'id DESC')
746 assert_equal 'Assigned to dlopper', j.notes
746 assert_equal 'Assigned to dlopper', j.notes
747 assert_equal 2, j.details.size
747 assert_equal 2, j.details.size
748
748
749 mail = ActionMailer::Base.deliveries.last
749 mail = ActionMailer::Base.deliveries.last
750 assert mail.body.include?("Status changed from New to Assigned")
750 assert mail.body.include?("Status changed from New to Assigned")
751 # subject should contain the new status
751 # subject should contain the new status
752 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
752 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
753 end
753 end
754
754
755 def test_put_update_with_note_only
755 def test_put_update_with_note_only
756 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
756 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
757 # anonymous user
757 # anonymous user
758 put :update,
758 put :update,
759 :id => 1,
759 :id => 1,
760 :notes => notes
760 :notes => notes
761 assert_redirected_to :action => 'show', :id => '1'
761 assert_redirected_to :action => 'show', :id => '1'
762 j = Journal.find(:first, :order => 'id DESC')
762 j = Journal.find(:first, :order => 'id DESC')
763 assert_equal notes, j.notes
763 assert_equal notes, j.notes
764 assert_equal 0, j.details.size
764 assert_equal 0, j.details.size
765 assert_equal User.anonymous, j.user
765 assert_equal User.anonymous, j.user
766
766
767 mail = ActionMailer::Base.deliveries.last
767 mail = ActionMailer::Base.deliveries.last
768 assert mail.body.include?(notes)
768 assert mail.body.include?(notes)
769 end
769 end
770
770
771 def test_put_update_with_note_and_spent_time
771 def test_put_update_with_note_and_spent_time
772 @request.session[:user_id] = 2
772 @request.session[:user_id] = 2
773 spent_hours_before = Issue.find(1).spent_hours
773 spent_hours_before = Issue.find(1).spent_hours
774 assert_difference('TimeEntry.count') do
774 assert_difference('TimeEntry.count') do
775 put :update,
775 put :update,
776 :id => 1,
776 :id => 1,
777 :notes => '2.5 hours added',
777 :notes => '2.5 hours added',
778 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
778 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
779 end
779 end
780 assert_redirected_to :action => 'show', :id => '1'
780 assert_redirected_to :action => 'show', :id => '1'
781
781
782 issue = Issue.find(1)
782 issue = Issue.find(1)
783
783
784 j = Journal.find(:first, :order => 'id DESC')
784 j = Journal.find(:first, :order => 'id DESC')
785 assert_equal '2.5 hours added', j.notes
785 assert_equal '2.5 hours added', j.notes
786 assert_equal 0, j.details.size
786 assert_equal 0, j.details.size
787
787
788 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
788 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
789 assert_not_nil t
789 assert_not_nil t
790 assert_equal 2.5, t.hours
790 assert_equal 2.5, t.hours
791 assert_equal spent_hours_before + 2.5, issue.spent_hours
791 assert_equal spent_hours_before + 2.5, issue.spent_hours
792 end
792 end
793
793
794 def test_put_update_with_attachment_only
794 def test_put_update_with_attachment_only
795 set_tmp_attachments_directory
795 set_tmp_attachments_directory
796
796
797 # Delete all fixtured journals, a race condition can occur causing the wrong
797 # Delete all fixtured journals, a race condition can occur causing the wrong
798 # journal to get fetched in the next find.
798 # journal to get fetched in the next find.
799 Journal.delete_all
799 Journal.delete_all
800
800
801 # anonymous user
801 # anonymous user
802 put :update,
802 put :update,
803 :id => 1,
803 :id => 1,
804 :notes => '',
804 :notes => '',
805 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
805 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
806 assert_redirected_to :action => 'show', :id => '1'
806 assert_redirected_to :action => 'show', :id => '1'
807 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
807 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
808 assert j.notes.blank?
808 assert j.notes.blank?
809 assert_equal 1, j.details.size
809 assert_equal 1, j.details.size
810 assert_equal 'testfile.txt', j.details.first.value
810 assert_equal 'testfile.txt', j.details.first.value
811 assert_equal User.anonymous, j.user
811 assert_equal User.anonymous, j.user
812
812
813 mail = ActionMailer::Base.deliveries.last
813 mail = ActionMailer::Base.deliveries.last
814 assert mail.body.include?('testfile.txt')
814 assert mail.body.include?('testfile.txt')
815 end
815 end
816
816
817 def test_put_update_with_attachment_that_fails_to_save
817 def test_put_update_with_attachment_that_fails_to_save
818 set_tmp_attachments_directory
818 set_tmp_attachments_directory
819
819
820 # Delete all fixtured journals, a race condition can occur causing the wrong
820 # Delete all fixtured journals, a race condition can occur causing the wrong
821 # journal to get fetched in the next find.
821 # journal to get fetched in the next find.
822 Journal.delete_all
822 Journal.delete_all
823
823
824 # Mock out the unsaved attachment
824 # Mock out the unsaved attachment
825 Attachment.any_instance.stubs(:create).returns(Attachment.new)
825 Attachment.any_instance.stubs(:create).returns(Attachment.new)
826
826
827 # anonymous user
827 # anonymous user
828 put :update,
828 put :update,
829 :id => 1,
829 :id => 1,
830 :notes => '',
830 :notes => '',
831 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
831 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
832 assert_redirected_to :action => 'show', :id => '1'
832 assert_redirected_to :action => 'show', :id => '1'
833 assert_equal '1 file(s) could not be saved.', flash[:warning]
833 assert_equal '1 file(s) could not be saved.', flash[:warning]
834
834
835 end if Object.const_defined?(:Mocha)
835 end if Object.const_defined?(:Mocha)
836
836
837 def test_put_update_with_no_change
837 def test_put_update_with_no_change
838 issue = Issue.find(1)
838 issue = Issue.find(1)
839 issue.journals.clear
839 issue.journals.clear
840 ActionMailer::Base.deliveries.clear
840 ActionMailer::Base.deliveries.clear
841
841
842 put :update,
842 put :update,
843 :id => 1,
843 :id => 1,
844 :notes => ''
844 :notes => ''
845 assert_redirected_to :action => 'show', :id => '1'
845 assert_redirected_to :action => 'show', :id => '1'
846
846
847 issue.reload
847 issue.reload
848 assert issue.journals.empty?
848 assert issue.journals.empty?
849 # No email should be sent
849 # No email should be sent
850 assert ActionMailer::Base.deliveries.empty?
850 assert ActionMailer::Base.deliveries.empty?
851 end
851 end
852
852
853 def test_put_update_should_send_a_notification
853 def test_put_update_should_send_a_notification
854 @request.session[:user_id] = 2
854 @request.session[:user_id] = 2
855 ActionMailer::Base.deliveries.clear
855 ActionMailer::Base.deliveries.clear
856 issue = Issue.find(1)
856 issue = Issue.find(1)
857 old_subject = issue.subject
857 old_subject = issue.subject
858 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
858 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
859
859
860 put :update, :id => 1, :issue => {:subject => new_subject,
860 put :update, :id => 1, :issue => {:subject => new_subject,
861 :priority_id => '6',
861 :priority_id => '6',
862 :category_id => '1' # no change
862 :category_id => '1' # no change
863 }
863 }
864 assert_equal 1, ActionMailer::Base.deliveries.size
864 assert_equal 1, ActionMailer::Base.deliveries.size
865 end
865 end
866
866
867 def test_put_update_with_invalid_spent_time
867 def test_put_update_with_invalid_spent_time
868 @request.session[:user_id] = 2
868 @request.session[:user_id] = 2
869 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
869 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
870
870
871 assert_no_difference('Journal.count') do
871 assert_no_difference('Journal.count') do
872 put :update,
872 put :update,
873 :id => 1,
873 :id => 1,
874 :notes => notes,
874 :notes => notes,
875 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
875 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
876 end
876 end
877 assert_response :success
877 assert_response :success
878 assert_template 'edit'
878 assert_template 'edit'
879
879
880 assert_tag :textarea, :attributes => { :name => 'notes' },
880 assert_tag :textarea, :attributes => { :name => 'notes' },
881 :content => notes
881 :content => notes
882 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
882 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
883 end
883 end
884
884
885 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
885 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
886 issue = Issue.find(2)
886 issue = Issue.find(2)
887 @request.session[:user_id] = 2
887 @request.session[:user_id] = 2
888
888
889 put :update,
889 put :update,
890 :id => issue.id,
890 :id => issue.id,
891 :issue => {
891 :issue => {
892 :fixed_version_id => 4
892 :fixed_version_id => 4
893 }
893 }
894
894
895 assert_response :redirect
895 assert_response :redirect
896 issue.reload
896 issue.reload
897 assert_equal 4, issue.fixed_version_id
897 assert_equal 4, issue.fixed_version_id
898 assert_not_equal issue.project_id, issue.fixed_version.project_id
898 assert_not_equal issue.project_id, issue.fixed_version.project_id
899 end
899 end
900
900
901 def test_put_update_should_redirect_back_using_the_back_url_parameter
901 def test_put_update_should_redirect_back_using_the_back_url_parameter
902 issue = Issue.find(2)
902 issue = Issue.find(2)
903 @request.session[:user_id] = 2
903 @request.session[:user_id] = 2
904
904
905 put :update,
905 put :update,
906 :id => issue.id,
906 :id => issue.id,
907 :issue => {
907 :issue => {
908 :fixed_version_id => 4
908 :fixed_version_id => 4
909 },
909 },
910 :back_url => '/issues'
910 :back_url => '/issues'
911
911
912 assert_response :redirect
912 assert_response :redirect
913 assert_redirected_to '/issues'
913 assert_redirected_to '/issues'
914 end
914 end
915
915
916 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
916 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
917 issue = Issue.find(2)
917 issue = Issue.find(2)
918 @request.session[:user_id] = 2
918 @request.session[:user_id] = 2
919
919
920 put :update,
920 put :update,
921 :id => issue.id,
921 :id => issue.id,
922 :issue => {
922 :issue => {
923 :fixed_version_id => 4
923 :fixed_version_id => 4
924 },
924 },
925 :back_url => 'http://google.com'
925 :back_url => 'http://google.com'
926
926
927 assert_response :redirect
927 assert_response :redirect
928 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
928 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
929 end
929 end
930
930
931 def test_get_bulk_edit
931 def test_get_bulk_edit
932 @request.session[:user_id] = 2
932 @request.session[:user_id] = 2
933 get :bulk_edit, :ids => [1, 2]
933 get :bulk_edit, :ids => [1, 2]
934 assert_response :success
934 assert_response :success
935 assert_template 'bulk_edit'
935 assert_template 'bulk_edit'
936
936
937 # Project specific custom field, date type
937 # Project specific custom field, date type
938 field = CustomField.find(9)
938 field = CustomField.find(9)
939 assert !field.is_for_all?
939 assert !field.is_for_all?
940 assert_equal 'date', field.field_format
940 assert_equal 'date', field.field_format
941 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
941 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
942
942
943 # System wide custom field
943 # System wide custom field
944 assert CustomField.find(1).is_for_all?
944 assert CustomField.find(1).is_for_all?
945 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
945 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
946 end
946 end
947
947
948 def test_bulk_edit
948 def test_bulk_edit
949 @request.session[:user_id] = 2
949 @request.session[:user_id] = 2
950 # update issues priority
950 # update issues priority
951 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing',
951 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing',
952 :issue => {:priority_id => 7,
952 :issue => {:priority_id => 7,
953 :assigned_to_id => '',
953 :assigned_to_id => '',
954 :custom_field_values => {'2' => ''}}
954 :custom_field_values => {'2' => ''}}
955
955
956 assert_response 302
956 assert_response 302
957 # check that the issues were updated
957 # check that the issues were updated
958 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
958 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
959
959
960 issue = Issue.find(1)
960 issue = Issue.find(1)
961 journal = issue.journals.find(:first, :order => 'created_on DESC')
961 journal = issue.journals.find(:first, :order => 'created_on DESC')
962 assert_equal '125', issue.custom_value_for(2).value
962 assert_equal '125', issue.custom_value_for(2).value
963 assert_equal 'Bulk editing', journal.notes
963 assert_equal 'Bulk editing', journal.notes
964 assert_equal 1, journal.details.size
964 assert_equal 1, journal.details.size
965 end
965 end
966
966
967 def test_bullk_edit_should_send_a_notification
967 def test_bullk_edit_should_send_a_notification
968 @request.session[:user_id] = 2
968 @request.session[:user_id] = 2
969 ActionMailer::Base.deliveries.clear
969 ActionMailer::Base.deliveries.clear
970 post(:bulk_edit,
970 post(:bulk_edit,
971 {
971 {
972 :ids => [1, 2],
972 :ids => [1, 2],
973 :notes => 'Bulk editing',
973 :notes => 'Bulk editing',
974 :issue => {
974 :issue => {
975 :priority_id => 7,
975 :priority_id => 7,
976 :assigned_to_id => '',
976 :assigned_to_id => '',
977 :custom_field_values => {'2' => ''}
977 :custom_field_values => {'2' => ''}
978 }
978 }
979 })
979 })
980
980
981 assert_response 302
981 assert_response 302
982 assert_equal 2, ActionMailer::Base.deliveries.size
982 assert_equal 2, ActionMailer::Base.deliveries.size
983 end
983 end
984
984
985 def test_bulk_edit_status
985 def test_bulk_edit_status
986 @request.session[:user_id] = 2
986 @request.session[:user_id] = 2
987 # update issues priority
987 # update issues priority
988 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status',
988 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status',
989 :issue => {:priority_id => '',
989 :issue => {:priority_id => '',
990 :assigned_to_id => '',
990 :assigned_to_id => '',
991 :status_id => '5'}
991 :status_id => '5'}
992
992
993 assert_response 302
993 assert_response 302
994 issue = Issue.find(1)
994 issue = Issue.find(1)
995 assert issue.closed?
995 assert issue.closed?
996 end
996 end
997
997
998 def test_bulk_edit_custom_field
998 def test_bulk_edit_custom_field
999 @request.session[:user_id] = 2
999 @request.session[:user_id] = 2
1000 # update issues priority
1000 # update issues priority
1001 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field',
1001 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field',
1002 :issue => {:priority_id => '',
1002 :issue => {:priority_id => '',
1003 :assigned_to_id => '',
1003 :assigned_to_id => '',
1004 :custom_field_values => {'2' => '777'}}
1004 :custom_field_values => {'2' => '777'}}
1005
1005
1006 assert_response 302
1006 assert_response 302
1007
1007
1008 issue = Issue.find(1)
1008 issue = Issue.find(1)
1009 journal = issue.journals.find(:first, :order => 'created_on DESC')
1009 journal = issue.journals.find(:first, :order => 'created_on DESC')
1010 assert_equal '777', issue.custom_value_for(2).value
1010 assert_equal '777', issue.custom_value_for(2).value
1011 assert_equal 1, journal.details.size
1011 assert_equal 1, journal.details.size
1012 assert_equal '125', journal.details.first.old_value
1012 assert_equal '125', journal.details.first.old_value
1013 assert_equal '777', journal.details.first.value
1013 assert_equal '777', journal.details.first.value
1014 end
1014 end
1015
1015
1016 def test_bulk_unassign
1016 def test_bulk_unassign
1017 assert_not_nil Issue.find(2).assigned_to
1017 assert_not_nil Issue.find(2).assigned_to
1018 @request.session[:user_id] = 2
1018 @request.session[:user_id] = 2
1019 # unassign issues
1019 # unassign issues
1020 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
1020 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
1021 assert_response 302
1021 assert_response 302
1022 # check that the issues were updated
1022 # check that the issues were updated
1023 assert_nil Issue.find(2).assigned_to
1023 assert_nil Issue.find(2).assigned_to
1024 end
1024 end
1025
1025
1026 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
1026 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
1027 @request.session[:user_id] = 2
1027 @request.session[:user_id] = 2
1028
1028
1029 post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4}
1029 post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4}
1030
1030
1031 assert_response :redirect
1031 assert_response :redirect
1032 issues = Issue.find([1,2])
1032 issues = Issue.find([1,2])
1033 issues.each do |issue|
1033 issues.each do |issue|
1034 assert_equal 4, issue.fixed_version_id
1034 assert_equal 4, issue.fixed_version_id
1035 assert_not_equal issue.project_id, issue.fixed_version.project_id
1035 assert_not_equal issue.project_id, issue.fixed_version.project_id
1036 end
1036 end
1037 end
1037 end
1038
1038
1039 def test_post_bulk_edit_should_redirect_back_using_the_back_url_parameter
1039 def test_post_bulk_edit_should_redirect_back_using_the_back_url_parameter
1040 @request.session[:user_id] = 2
1040 @request.session[:user_id] = 2
1041 post :bulk_edit, :ids => [1,2], :back_url => '/issues'
1041 post :bulk_edit, :ids => [1,2], :back_url => '/issues'
1042
1042
1043 assert_response :redirect
1043 assert_response :redirect
1044 assert_redirected_to '/issues'
1044 assert_redirected_to '/issues'
1045 end
1045 end
1046
1046
1047 def test_post_bulk_edit_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1047 def test_post_bulk_edit_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1048 @request.session[:user_id] = 2
1048 @request.session[:user_id] = 2
1049 post :bulk_edit, :ids => [1,2], :back_url => 'http://google.com'
1049 post :bulk_edit, :ids => [1,2], :back_url => 'http://google.com'
1050
1050
1051 assert_response :redirect
1051 assert_response :redirect
1052 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1052 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1053 end
1053 end
1054
1054
1055 def test_move_one_issue_to_another_project
1055 def test_move_one_issue_to_another_project
1056 @request.session[:user_id] = 2
1056 @request.session[:user_id] = 2
1057 post :move, :id => 1, :new_project_id => 2, :tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1057 post :move, :id => 1, :new_project_id => 2, :tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1058 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1058 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1059 assert_equal 2, Issue.find(1).project_id
1059 assert_equal 2, Issue.find(1).project_id
1060 end
1060 end
1061
1061
1062 def test_move_one_issue_to_another_project_should_follow_when_needed
1062 def test_move_one_issue_to_another_project_should_follow_when_needed
1063 @request.session[:user_id] = 2
1063 @request.session[:user_id] = 2
1064 post :move, :id => 1, :new_project_id => 2, :follow => '1'
1064 post :move, :id => 1, :new_project_id => 2, :follow => '1'
1065 assert_redirected_to '/issues/1'
1065 assert_redirected_to '/issues/1'
1066 end
1066 end
1067
1067
1068 def test_bulk_move_to_another_project
1068 def test_bulk_move_to_another_project
1069 @request.session[:user_id] = 2
1069 @request.session[:user_id] = 2
1070 post :move, :ids => [1, 2], :new_project_id => 2
1070 post :move, :ids => [1, 2], :new_project_id => 2
1071 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1071 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1072 # Issues moved to project 2
1072 # Issues moved to project 2
1073 assert_equal 2, Issue.find(1).project_id
1073 assert_equal 2, Issue.find(1).project_id
1074 assert_equal 2, Issue.find(2).project_id
1074 assert_equal 2, Issue.find(2).project_id
1075 # No tracker change
1075 # No tracker change
1076 assert_equal 1, Issue.find(1).tracker_id
1076 assert_equal 1, Issue.find(1).tracker_id
1077 assert_equal 2, Issue.find(2).tracker_id
1077 assert_equal 2, Issue.find(2).tracker_id
1078 end
1078 end
1079
1079
1080 def test_bulk_move_to_another_tracker
1080 def test_bulk_move_to_another_tracker
1081 @request.session[:user_id] = 2
1081 @request.session[:user_id] = 2
1082 post :move, :ids => [1, 2], :new_tracker_id => 2
1082 post :move, :ids => [1, 2], :new_tracker_id => 2
1083 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1083 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1084 assert_equal 2, Issue.find(1).tracker_id
1084 assert_equal 2, Issue.find(1).tracker_id
1085 assert_equal 2, Issue.find(2).tracker_id
1085 assert_equal 2, Issue.find(2).tracker_id
1086 end
1086 end
1087
1087
1088 def test_bulk_copy_to_another_project
1088 def test_bulk_copy_to_another_project
1089 @request.session[:user_id] = 2
1089 @request.session[:user_id] = 2
1090 assert_difference 'Issue.count', 2 do
1090 assert_difference 'Issue.count', 2 do
1091 assert_no_difference 'Project.find(1).issues.count' do
1091 assert_no_difference 'Project.find(1).issues.count' do
1092 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}
1092 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}
1093 end
1093 end
1094 end
1094 end
1095 assert_redirected_to 'projects/ecookbook/issues'
1095 assert_redirected_to 'projects/ecookbook/issues'
1096 end
1096 end
1097
1097
1098 context "#move via bulk copy" do
1098 context "#move via bulk copy" do
1099 should "allow not changing the issue's attributes" do
1099 should "allow not changing the issue's attributes" do
1100 @request.session[:user_id] = 2
1100 @request.session[:user_id] = 2
1101 issue_before_move = Issue.find(1)
1101 issue_before_move = Issue.find(1)
1102 assert_difference 'Issue.count', 1 do
1102 assert_difference 'Issue.count', 1 do
1103 assert_no_difference 'Project.find(1).issues.count' do
1103 assert_no_difference 'Project.find(1).issues.count' do
1104 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1104 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1105 end
1105 end
1106 end
1106 end
1107 issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2})
1107 issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2})
1108 assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id
1108 assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id
1109 assert_equal issue_before_move.status_id, issue_after_move.status_id
1109 assert_equal issue_before_move.status_id, issue_after_move.status_id
1110 assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id
1110 assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id
1111 end
1111 end
1112
1112
1113 should "allow changing the issue's attributes" do
1113 should "allow changing the issue's attributes" do
1114 # Fixes random test failure with Mysql
1115 # where Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2}) doesn't return the expected results
1116 Issue.delete_all("project_id=2")
1117
1114 @request.session[:user_id] = 2
1118 @request.session[:user_id] = 2
1115 assert_difference 'Issue.count', 2 do
1119 assert_difference 'Issue.count', 2 do
1116 assert_no_difference 'Project.find(1).issues.count' do
1120 assert_no_difference 'Project.find(1).issues.count' do
1117 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => 4, :status_id => 3, :start_date => '2009-12-01', :due_date => '2009-12-31'
1121 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => 4, :status_id => 3, :start_date => '2009-12-01', :due_date => '2009-12-31'
1118 end
1122 end
1119 end
1123 end
1120
1124
1121 copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
1125 copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
1122 assert_equal 2, copied_issues.size
1126 assert_equal 2, copied_issues.size
1123 copied_issues.each do |issue|
1127 copied_issues.each do |issue|
1124 assert_equal 2, issue.project_id, "Project is incorrect"
1128 assert_equal 2, issue.project_id, "Project is incorrect"
1125 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
1129 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
1126 assert_equal 3, issue.status_id, "Status is incorrect"
1130 assert_equal 3, issue.status_id, "Status is incorrect"
1127 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
1131 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
1128 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
1132 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
1129 end
1133 end
1130 end
1134 end
1131 end
1135 end
1132
1136
1133 def test_copy_to_another_project_should_follow_when_needed
1137 def test_copy_to_another_project_should_follow_when_needed
1134 @request.session[:user_id] = 2
1138 @request.session[:user_id] = 2
1135 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :follow => '1'
1139 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :follow => '1'
1136 issue = Issue.first(:order => 'id DESC')
1140 issue = Issue.first(:order => 'id DESC')
1137 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
1141 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
1138 end
1142 end
1139
1143
1140 def test_context_menu_one_issue
1144 def test_context_menu_one_issue
1141 @request.session[:user_id] = 2
1145 @request.session[:user_id] = 2
1142 get :context_menu, :ids => [1]
1146 get :context_menu, :ids => [1]
1143 assert_response :success
1147 assert_response :success
1144 assert_template 'context_menu'
1148 assert_template 'context_menu'
1145 assert_tag :tag => 'a', :content => 'Edit',
1149 assert_tag :tag => 'a', :content => 'Edit',
1146 :attributes => { :href => '/issues/1/edit',
1150 :attributes => { :href => '/issues/1/edit',
1147 :class => 'icon-edit' }
1151 :class => 'icon-edit' }
1148 assert_tag :tag => 'a', :content => 'Closed',
1152 assert_tag :tag => 'a', :content => 'Closed',
1149 :attributes => { :href => '/issues/1/edit?issue%5Bstatus_id%5D=5',
1153 :attributes => { :href => '/issues/1/edit?issue%5Bstatus_id%5D=5',
1150 :class => '' }
1154 :class => '' }
1151 assert_tag :tag => 'a', :content => 'Immediate',
1155 assert_tag :tag => 'a', :content => 'Immediate',
1152 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8',
1156 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8',
1153 :class => '' }
1157 :class => '' }
1154 # Versions
1158 # Versions
1155 assert_tag :tag => 'a', :content => '2.0',
1159 assert_tag :tag => 'a', :content => '2.0',
1156 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3',
1160 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3',
1157 :class => '' }
1161 :class => '' }
1158 assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
1162 assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
1159 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4',
1163 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4',
1160 :class => '' }
1164 :class => '' }
1161
1165
1162 assert_tag :tag => 'a', :content => 'Dave Lopper',
1166 assert_tag :tag => 'a', :content => 'Dave Lopper',
1163 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3',
1167 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3',
1164 :class => '' }
1168 :class => '' }
1165 assert_tag :tag => 'a', :content => 'Duplicate',
1169 assert_tag :tag => 'a', :content => 'Duplicate',
1166 :attributes => { :href => '/projects/ecookbook/issues/1/copy',
1170 :attributes => { :href => '/projects/ecookbook/issues/1/copy',
1167 :class => 'icon-duplicate' }
1171 :class => 'icon-duplicate' }
1168 assert_tag :tag => 'a', :content => 'Copy',
1172 assert_tag :tag => 'a', :content => 'Copy',
1169 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1',
1173 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1',
1170 :class => 'icon-copy' }
1174 :class => 'icon-copy' }
1171 assert_tag :tag => 'a', :content => 'Move',
1175 assert_tag :tag => 'a', :content => 'Move',
1172 :attributes => { :href => '/issues/move?ids%5B%5D=1',
1176 :attributes => { :href => '/issues/move?ids%5B%5D=1',
1173 :class => 'icon-move' }
1177 :class => 'icon-move' }
1174 assert_tag :tag => 'a', :content => 'Delete',
1178 assert_tag :tag => 'a', :content => 'Delete',
1175 :attributes => { :href => '/issues/destroy?ids%5B%5D=1',
1179 :attributes => { :href => '/issues/destroy?ids%5B%5D=1',
1176 :class => 'icon-del' }
1180 :class => 'icon-del' }
1177 end
1181 end
1178
1182
1179 def test_context_menu_one_issue_by_anonymous
1183 def test_context_menu_one_issue_by_anonymous
1180 get :context_menu, :ids => [1]
1184 get :context_menu, :ids => [1]
1181 assert_response :success
1185 assert_response :success
1182 assert_template 'context_menu'
1186 assert_template 'context_menu'
1183 assert_tag :tag => 'a', :content => 'Delete',
1187 assert_tag :tag => 'a', :content => 'Delete',
1184 :attributes => { :href => '#',
1188 :attributes => { :href => '#',
1185 :class => 'icon-del disabled' }
1189 :class => 'icon-del disabled' }
1186 end
1190 end
1187
1191
1188 def test_context_menu_multiple_issues_of_same_project
1192 def test_context_menu_multiple_issues_of_same_project
1189 @request.session[:user_id] = 2
1193 @request.session[:user_id] = 2
1190 get :context_menu, :ids => [1, 2]
1194 get :context_menu, :ids => [1, 2]
1191 assert_response :success
1195 assert_response :success
1192 assert_template 'context_menu'
1196 assert_template 'context_menu'
1193 assert_tag :tag => 'a', :content => 'Edit',
1197 assert_tag :tag => 'a', :content => 'Edit',
1194 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2',
1198 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2',
1195 :class => 'icon-edit' }
1199 :class => 'icon-edit' }
1196 assert_tag :tag => 'a', :content => 'Immediate',
1200 assert_tag :tag => 'a', :content => 'Immediate',
1197 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bpriority_id%5D=8',
1201 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bpriority_id%5D=8',
1198 :class => '' }
1202 :class => '' }
1199 assert_tag :tag => 'a', :content => 'Dave Lopper',
1203 assert_tag :tag => 'a', :content => 'Dave Lopper',
1200 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bassigned_to_id%5D=3',
1204 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bassigned_to_id%5D=3',
1201 :class => '' }
1205 :class => '' }
1202 assert_tag :tag => 'a', :content => 'Copy',
1206 assert_tag :tag => 'a', :content => 'Copy',
1203 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1&amp;ids%5B%5D=2',
1207 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1&amp;ids%5B%5D=2',
1204 :class => 'icon-copy' }
1208 :class => 'icon-copy' }
1205 assert_tag :tag => 'a', :content => 'Move',
1209 assert_tag :tag => 'a', :content => 'Move',
1206 :attributes => { :href => '/issues/move?ids%5B%5D=1&amp;ids%5B%5D=2',
1210 :attributes => { :href => '/issues/move?ids%5B%5D=1&amp;ids%5B%5D=2',
1207 :class => 'icon-move' }
1211 :class => 'icon-move' }
1208 assert_tag :tag => 'a', :content => 'Delete',
1212 assert_tag :tag => 'a', :content => 'Delete',
1209 :attributes => { :href => '/issues/destroy?ids%5B%5D=1&amp;ids%5B%5D=2',
1213 :attributes => { :href => '/issues/destroy?ids%5B%5D=1&amp;ids%5B%5D=2',
1210 :class => 'icon-del' }
1214 :class => 'icon-del' }
1211 end
1215 end
1212
1216
1213 def test_context_menu_multiple_issues_of_different_project
1217 def test_context_menu_multiple_issues_of_different_project
1214 @request.session[:user_id] = 2
1218 @request.session[:user_id] = 2
1215 get :context_menu, :ids => [1, 2, 4]
1219 get :context_menu, :ids => [1, 2, 4]
1216 assert_response :success
1220 assert_response :success
1217 assert_template 'context_menu'
1221 assert_template 'context_menu'
1218 assert_tag :tag => 'a', :content => 'Delete',
1222 assert_tag :tag => 'a', :content => 'Delete',
1219 :attributes => { :href => '#',
1223 :attributes => { :href => '#',
1220 :class => 'icon-del disabled' }
1224 :class => 'icon-del disabled' }
1221 end
1225 end
1222
1226
1223 def test_preview_new_issue
1227 def test_preview_new_issue
1224 @request.session[:user_id] = 2
1228 @request.session[:user_id] = 2
1225 post :preview, :project_id => '1', :issue => {:description => 'Foo'}
1229 post :preview, :project_id => '1', :issue => {:description => 'Foo'}
1226 assert_response :success
1230 assert_response :success
1227 assert_template 'preview'
1231 assert_template 'preview'
1228 assert_not_nil assigns(:description)
1232 assert_not_nil assigns(:description)
1229 end
1233 end
1230
1234
1231 def test_preview_notes
1235 def test_preview_notes
1232 @request.session[:user_id] = 2
1236 @request.session[:user_id] = 2
1233 post :preview, :project_id => '1', :id => 1, :issue => {:description => Issue.find(1).description}, :notes => 'Foo'
1237 post :preview, :project_id => '1', :id => 1, :issue => {:description => Issue.find(1).description}, :notes => 'Foo'
1234 assert_response :success
1238 assert_response :success
1235 assert_template 'preview'
1239 assert_template 'preview'
1236 assert_not_nil assigns(:notes)
1240 assert_not_nil assigns(:notes)
1237 end
1241 end
1238
1242
1239 def test_auto_complete_should_not_be_case_sensitive
1243 def test_auto_complete_should_not_be_case_sensitive
1240 get :auto_complete, :project_id => 'ecookbook', :q => 'ReCiPe'
1244 get :auto_complete, :project_id => 'ecookbook', :q => 'ReCiPe'
1241 assert_response :success
1245 assert_response :success
1242 assert_not_nil assigns(:issues)
1246 assert_not_nil assigns(:issues)
1243 assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
1247 assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
1244 end
1248 end
1245
1249
1246 def test_auto_complete_should_return_issue_with_given_id
1250 def test_auto_complete_should_return_issue_with_given_id
1247 get :auto_complete, :project_id => 'subproject1', :q => '13'
1251 get :auto_complete, :project_id => 'subproject1', :q => '13'
1248 assert_response :success
1252 assert_response :success
1249 assert_not_nil assigns(:issues)
1253 assert_not_nil assigns(:issues)
1250 assert assigns(:issues).include?(Issue.find(13))
1254 assert assigns(:issues).include?(Issue.find(13))
1251 end
1255 end
1252
1256
1253 def test_destroy_issue_with_no_time_entries
1257 def test_destroy_issue_with_no_time_entries
1254 assert_nil TimeEntry.find_by_issue_id(2)
1258 assert_nil TimeEntry.find_by_issue_id(2)
1255 @request.session[:user_id] = 2
1259 @request.session[:user_id] = 2
1256 post :destroy, :id => 2
1260 post :destroy, :id => 2
1257 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1261 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1258 assert_nil Issue.find_by_id(2)
1262 assert_nil Issue.find_by_id(2)
1259 end
1263 end
1260
1264
1261 def test_destroy_issues_with_time_entries
1265 def test_destroy_issues_with_time_entries
1262 @request.session[:user_id] = 2
1266 @request.session[:user_id] = 2
1263 post :destroy, :ids => [1, 3]
1267 post :destroy, :ids => [1, 3]
1264 assert_response :success
1268 assert_response :success
1265 assert_template 'destroy'
1269 assert_template 'destroy'
1266 assert_not_nil assigns(:hours)
1270 assert_not_nil assigns(:hours)
1267 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1271 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1268 end
1272 end
1269
1273
1270 def test_destroy_issues_and_destroy_time_entries
1274 def test_destroy_issues_and_destroy_time_entries
1271 @request.session[:user_id] = 2
1275 @request.session[:user_id] = 2
1272 post :destroy, :ids => [1, 3], :todo => 'destroy'
1276 post :destroy, :ids => [1, 3], :todo => 'destroy'
1273 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1277 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1274 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1278 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1275 assert_nil TimeEntry.find_by_id([1, 2])
1279 assert_nil TimeEntry.find_by_id([1, 2])
1276 end
1280 end
1277
1281
1278 def test_destroy_issues_and_assign_time_entries_to_project
1282 def test_destroy_issues_and_assign_time_entries_to_project
1279 @request.session[:user_id] = 2
1283 @request.session[:user_id] = 2
1280 post :destroy, :ids => [1, 3], :todo => 'nullify'
1284 post :destroy, :ids => [1, 3], :todo => 'nullify'
1281 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1285 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1282 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1286 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1283 assert_nil TimeEntry.find(1).issue_id
1287 assert_nil TimeEntry.find(1).issue_id
1284 assert_nil TimeEntry.find(2).issue_id
1288 assert_nil TimeEntry.find(2).issue_id
1285 end
1289 end
1286
1290
1287 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1291 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1288 @request.session[:user_id] = 2
1292 @request.session[:user_id] = 2
1289 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1293 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1290 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1294 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1291 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1295 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1292 assert_equal 2, TimeEntry.find(1).issue_id
1296 assert_equal 2, TimeEntry.find(1).issue_id
1293 assert_equal 2, TimeEntry.find(2).issue_id
1297 assert_equal 2, TimeEntry.find(2).issue_id
1294 end
1298 end
1295
1299
1296 def test_default_search_scope
1300 def test_default_search_scope
1297 get :index
1301 get :index
1298 assert_tag :div, :attributes => {:id => 'quick-search'},
1302 assert_tag :div, :attributes => {:id => 'quick-search'},
1299 :child => {:tag => 'form',
1303 :child => {:tag => 'form',
1300 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1304 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1301 end
1305 end
1302 end
1306 end
General Comments 0
You need to be logged in to leave comments. Login now