##// END OF EJS Templates
Merged r13556 (#13673)....
Jean-Philippe Lang -
r13246:fa4b6f294b16
parent child
Show More
@@ -1,200 +1,202
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2014 Jean-Philippe Lang
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; either version 2
9 9 # of the License, or (at your option) any later version.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
20 20 module QueriesHelper
21 21 include ApplicationHelper
22 22
23 23 def filters_options_for_select(query)
24 24 options_for_select(filters_options(query))
25 25 end
26 26
27 27 def filters_options(query)
28 28 options = [[]]
29 29 options += query.available_filters.map do |field, field_options|
30 30 [field_options[:name], field]
31 31 end
32 32 end
33 33
34 34 def query_filters_hidden_tags(query)
35 35 tags = ''.html_safe
36 36 query.filters.each do |field, options|
37 37 tags << hidden_field_tag("f[]", field, :id => nil)
38 38 tags << hidden_field_tag("op[#{field}]", options[:operator], :id => nil)
39 39 options[:values].each do |value|
40 40 tags << hidden_field_tag("v[#{field}][]", value, :id => nil)
41 41 end
42 42 end
43 43 tags
44 44 end
45 45
46 46 def query_columns_hidden_tags(query)
47 47 tags = ''.html_safe
48 48 query.columns.each do |column|
49 49 tags << hidden_field_tag("c[]", column.name, :id => nil)
50 50 end
51 51 tags
52 52 end
53 53
54 54 def query_hidden_tags(query)
55 55 query_filters_hidden_tags(query) + query_columns_hidden_tags(query)
56 56 end
57 57
58 58 def available_block_columns_tags(query)
59 59 tags = ''.html_safe
60 60 query.available_block_columns.each do |column|
61 61 tags << content_tag('label', check_box_tag('c[]', column.name.to_s, query.has_column?(column), :id => nil) + " #{column.caption}", :class => 'inline')
62 62 end
63 63 tags
64 64 end
65 65
66 66 def query_available_inline_columns_options(query)
67 67 (query.available_inline_columns - query.columns).reject(&:frozen?).collect {|column| [column.caption, column.name]}
68 68 end
69 69
70 70 def query_selected_inline_columns_options(query)
71 71 (query.inline_columns & query.available_inline_columns).reject(&:frozen?).collect {|column| [column.caption, column.name]}
72 72 end
73 73
74 74 def render_query_columns_selection(query, options={})
75 75 tag_name = (options[:name] || 'c') + '[]'
76 76 render :partial => 'queries/columns', :locals => {:query => query, :tag_name => tag_name}
77 77 end
78 78
79 79 def column_header(column)
80 80 column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption,
81 81 :default_order => column.default_order) :
82 82 content_tag('th', h(column.caption))
83 83 end
84 84
85 85 def column_content(column, issue)
86 86 value = column.value_object(issue)
87 87 if value.is_a?(Array)
88 88 value.collect {|v| column_value(column, issue, v)}.compact.join(', ').html_safe
89 89 else
90 90 column_value(column, issue, value)
91 91 end
92 92 end
93 93
94 94 def column_value(column, issue, value)
95 95 case column.name
96 96 when :id
97 97 link_to value, issue_path(issue)
98 98 when :subject
99 99 link_to value, issue_path(issue)
100 when :parent
101 value ? (value.visible? ? link_to_issue(value, :subject => false) : "##{value.id}") : ''
100 102 when :description
101 103 issue.description? ? content_tag('div', textilizable(issue, :description), :class => "wiki") : ''
102 104 when :done_ratio
103 105 progress_bar(value, :width => '80px')
104 106 when :relations
105 107 other = value.other_issue(issue)
106 108 content_tag('span',
107 109 (l(value.label_for(issue)) + " " + link_to_issue(other, :subject => false, :tracker => false)).html_safe,
108 110 :class => value.css_classes_for(issue))
109 111 else
110 112 format_object(value)
111 113 end
112 114 end
113 115
114 116 def csv_content(column, issue)
115 117 value = column.value_object(issue)
116 118 if value.is_a?(Array)
117 119 value.collect {|v| csv_value(column, issue, v)}.compact.join(', ')
118 120 else
119 121 csv_value(column, issue, value)
120 122 end
121 123 end
122 124
123 125 def csv_value(column, issue, value)
124 126 format_object(value, false) do |value|
125 127 case value.class.name
126 128 when 'Float'
127 129 sprintf("%.2f", value).gsub('.', l(:general_csv_decimal_separator))
128 130 when 'IssueRelation'
129 131 other = value.other_issue(issue)
130 132 l(value.label_for(issue)) + " ##{other.id}"
131 133 when 'Issue'
132 134 value.id
133 135 else
134 136 value
135 137 end
136 138 end
137 139 end
138 140
139 141 def query_to_csv(items, query, options={})
140 142 encoding = l(:general_csv_encoding)
141 143 columns = (options[:columns] == 'all' ? query.available_inline_columns : query.inline_columns)
142 144 query.available_block_columns.each do |column|
143 145 if options[column.name].present?
144 146 columns << column
145 147 end
146 148 end
147 149
148 150 export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
149 151 # csv header fields
150 152 csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) }
151 153 # csv lines
152 154 items.each do |item|
153 155 csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(csv_content(c, item), encoding) }
154 156 end
155 157 end
156 158 export
157 159 end
158 160
159 161 # Retrieve query from session or build a new query
160 162 def retrieve_query
161 163 if !params[:query_id].blank?
162 164 cond = "project_id IS NULL"
163 165 cond << " OR project_id = #{@project.id}" if @project
164 166 @query = IssueQuery.where(cond).find(params[:query_id])
165 167 raise ::Unauthorized unless @query.visible?
166 168 @query.project = @project
167 169 session[:query] = {:id => @query.id, :project_id => @query.project_id}
168 170 sort_clear
169 171 elsif api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
170 172 # Give it a name, required to be valid
171 173 @query = IssueQuery.new(:name => "_")
172 174 @query.project = @project
173 175 @query.build_from_params(params)
174 176 session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
175 177 else
176 178 # retrieve from session
177 179 @query = nil
178 180 @query = IssueQuery.find_by_id(session[:query][:id]) if session[:query][:id]
179 181 @query ||= IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
180 182 @query.project = @project
181 183 end
182 184 end
183 185
184 186 def retrieve_query_from_session
185 187 if session[:query]
186 188 if session[:query][:id]
187 189 @query = IssueQuery.find_by_id(session[:query][:id])
188 190 return unless @query
189 191 else
190 192 @query = IssueQuery.new(:name => "_", :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
191 193 end
192 194 if session[:query].has_key?(:project_id)
193 195 @query.project_id = session[:query][:project_id]
194 196 else
195 197 @query.project = @project
196 198 end
197 199 @query
198 200 end
199 201 end
200 202 end
@@ -1,4023 +1,4034
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class IssuesControllerTest < ActionController::TestCase
21 21 fixtures :projects,
22 22 :users,
23 23 :roles,
24 24 :members,
25 25 :member_roles,
26 26 :issues,
27 27 :issue_statuses,
28 28 :issue_relations,
29 29 :versions,
30 30 :trackers,
31 31 :projects_trackers,
32 32 :issue_categories,
33 33 :enabled_modules,
34 34 :enumerations,
35 35 :attachments,
36 36 :workflows,
37 37 :custom_fields,
38 38 :custom_values,
39 39 :custom_fields_projects,
40 40 :custom_fields_trackers,
41 41 :time_entries,
42 42 :journals,
43 43 :journal_details,
44 44 :queries,
45 45 :repositories,
46 46 :changesets
47 47
48 48 include Redmine::I18n
49 49
50 50 def setup
51 51 User.current = nil
52 52 end
53 53
54 54 def test_index
55 55 with_settings :default_language => "en" do
56 56 get :index
57 57 assert_response :success
58 58 assert_template 'index'
59 59 assert_not_nil assigns(:issues)
60 60 assert_nil assigns(:project)
61 61
62 62 # links to visible issues
63 63 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
64 64 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
65 65 # private projects hidden
66 66 assert_select 'a[href=/issues/6]', 0
67 67 assert_select 'a[href=/issues/4]', 0
68 68 # project column
69 69 assert_select 'th', :text => /Project/
70 70 end
71 71 end
72 72
73 73 def test_index_should_not_list_issues_when_module_disabled
74 74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
75 75 get :index
76 76 assert_response :success
77 77 assert_template 'index'
78 78 assert_not_nil assigns(:issues)
79 79 assert_nil assigns(:project)
80 80
81 81 assert_select 'a[href=/issues/1]', 0
82 82 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
83 83 end
84 84
85 85 def test_index_should_list_visible_issues_only
86 86 get :index, :per_page => 100
87 87 assert_response :success
88 88 assert_not_nil assigns(:issues)
89 89 assert_nil assigns(:issues).detect {|issue| !issue.visible?}
90 90 end
91 91
92 92 def test_index_with_project
93 93 Setting.display_subprojects_issues = 0
94 94 get :index, :project_id => 1
95 95 assert_response :success
96 96 assert_template 'index'
97 97 assert_not_nil assigns(:issues)
98 98
99 99 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
100 100 assert_select 'a[href=/issues/5]', 0
101 101 end
102 102
103 103 def test_index_with_project_and_subprojects
104 104 Setting.display_subprojects_issues = 1
105 105 get :index, :project_id => 1
106 106 assert_response :success
107 107 assert_template 'index'
108 108 assert_not_nil assigns(:issues)
109 109
110 110 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
111 111 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
112 112 assert_select 'a[href=/issues/6]', 0
113 113 end
114 114
115 115 def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
116 116 @request.session[:user_id] = 2
117 117 Setting.display_subprojects_issues = 1
118 118 get :index, :project_id => 1
119 119 assert_response :success
120 120 assert_template 'index'
121 121 assert_not_nil assigns(:issues)
122 122
123 123 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
124 124 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
125 125 assert_select 'a[href=/issues/6]', :text => /Issue of a private subproject/
126 126 end
127 127
128 128 def test_index_with_project_and_default_filter
129 129 get :index, :project_id => 1, :set_filter => 1
130 130 assert_response :success
131 131 assert_template 'index'
132 132 assert_not_nil assigns(:issues)
133 133
134 134 query = assigns(:query)
135 135 assert_not_nil query
136 136 # default filter
137 137 assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
138 138 end
139 139
140 140 def test_index_with_project_and_filter
141 141 get :index, :project_id => 1, :set_filter => 1,
142 142 :f => ['tracker_id'],
143 143 :op => {'tracker_id' => '='},
144 144 :v => {'tracker_id' => ['1']}
145 145 assert_response :success
146 146 assert_template 'index'
147 147 assert_not_nil assigns(:issues)
148 148
149 149 query = assigns(:query)
150 150 assert_not_nil query
151 151 assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
152 152 end
153 153
154 154 def test_index_with_short_filters
155 155 to_test = {
156 156 'status_id' => {
157 157 'o' => { :op => 'o', :values => [''] },
158 158 'c' => { :op => 'c', :values => [''] },
159 159 '7' => { :op => '=', :values => ['7'] },
160 160 '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
161 161 '=7' => { :op => '=', :values => ['7'] },
162 162 '!3' => { :op => '!', :values => ['3'] },
163 163 '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
164 164 'subject' => {
165 165 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
166 166 'o' => { :op => '=', :values => ['o'] },
167 167 '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
168 168 '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
169 169 'tracker_id' => {
170 170 '3' => { :op => '=', :values => ['3'] },
171 171 '=3' => { :op => '=', :values => ['3'] }},
172 172 'start_date' => {
173 173 '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
174 174 '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
175 175 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
176 176 '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
177 177 '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
178 178 '<t+2' => { :op => '<t+', :values => ['2'] },
179 179 '>t+2' => { :op => '>t+', :values => ['2'] },
180 180 't+2' => { :op => 't+', :values => ['2'] },
181 181 't' => { :op => 't', :values => [''] },
182 182 'w' => { :op => 'w', :values => [''] },
183 183 '>t-2' => { :op => '>t-', :values => ['2'] },
184 184 '<t-2' => { :op => '<t-', :values => ['2'] },
185 185 't-2' => { :op => 't-', :values => ['2'] }},
186 186 'created_on' => {
187 187 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
188 188 '<t-2' => { :op => '<t-', :values => ['2'] },
189 189 '>t-2' => { :op => '>t-', :values => ['2'] },
190 190 't-2' => { :op => 't-', :values => ['2'] }},
191 191 'cf_1' => {
192 192 'c' => { :op => '=', :values => ['c'] },
193 193 '!c' => { :op => '!', :values => ['c'] },
194 194 '!*' => { :op => '!*', :values => [''] },
195 195 '*' => { :op => '*', :values => [''] }},
196 196 'estimated_hours' => {
197 197 '=13.4' => { :op => '=', :values => ['13.4'] },
198 198 '>=45' => { :op => '>=', :values => ['45'] },
199 199 '<=125' => { :op => '<=', :values => ['125'] },
200 200 '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
201 201 '!*' => { :op => '!*', :values => [''] },
202 202 '*' => { :op => '*', :values => [''] }}
203 203 }
204 204
205 205 default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
206 206
207 207 to_test.each do |field, expression_and_expected|
208 208 expression_and_expected.each do |filter_expression, expected|
209 209
210 210 get :index, :set_filter => 1, field => filter_expression
211 211
212 212 assert_response :success
213 213 assert_template 'index'
214 214 assert_not_nil assigns(:issues)
215 215
216 216 query = assigns(:query)
217 217 assert_not_nil query
218 218 assert query.has_filter?(field)
219 219 assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
220 220 end
221 221 end
222 222 end
223 223
224 224 def test_index_with_project_and_empty_filters
225 225 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
226 226 assert_response :success
227 227 assert_template 'index'
228 228 assert_not_nil assigns(:issues)
229 229
230 230 query = assigns(:query)
231 231 assert_not_nil query
232 232 # no filter
233 233 assert_equal({}, query.filters)
234 234 end
235 235
236 236 def test_index_with_project_custom_field_filter
237 237 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
238 238 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
239 239 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
240 240 filter_name = "project.cf_#{field.id}"
241 241 @request.session[:user_id] = 1
242 242
243 243 get :index, :set_filter => 1,
244 244 :f => [filter_name],
245 245 :op => {filter_name => '='},
246 246 :v => {filter_name => ['Foo']}
247 247 assert_response :success
248 248 assert_template 'index'
249 249 assert_equal [3, 5], assigns(:issues).map(&:project_id).uniq.sort
250 250 end
251 251
252 252 def test_index_with_query
253 253 get :index, :project_id => 1, :query_id => 5
254 254 assert_response :success
255 255 assert_template 'index'
256 256 assert_not_nil assigns(:issues)
257 257 assert_nil assigns(:issue_count_by_group)
258 258 end
259 259
260 260 def test_index_with_query_grouped_by_tracker
261 261 get :index, :project_id => 1, :query_id => 6
262 262 assert_response :success
263 263 assert_template 'index'
264 264 assert_not_nil assigns(:issues)
265 265 assert_not_nil assigns(:issue_count_by_group)
266 266 end
267 267
268 268 def test_index_with_query_grouped_by_list_custom_field
269 269 get :index, :project_id => 1, :query_id => 9
270 270 assert_response :success
271 271 assert_template 'index'
272 272 assert_not_nil assigns(:issues)
273 273 assert_not_nil assigns(:issue_count_by_group)
274 274 end
275 275
276 276 def test_index_with_query_grouped_by_user_custom_field
277 277 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
278 278 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
279 279 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
280 280 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
281 281 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
282 282
283 283 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
284 284 assert_response :success
285 285
286 286 assert_select 'tr.group', 3
287 287 assert_select 'tr.group' do
288 288 assert_select 'a', :text => 'John Smith'
289 289 assert_select 'span.count', :text => '1'
290 290 end
291 291 assert_select 'tr.group' do
292 292 assert_select 'a', :text => 'Dave Lopper'
293 293 assert_select 'span.count', :text => '2'
294 294 end
295 295 end
296 296
297 297 def test_index_with_query_grouped_by_tracker_in_normal_order
298 298 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
299 299
300 300 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc'
301 301 assert_response :success
302 302
303 303 trackers = assigns(:issues).map(&:tracker).uniq
304 304 assert_equal [1, 2, 3], trackers.map(&:id)
305 305 end
306 306
307 307 def test_index_with_query_grouped_by_tracker_in_reverse_order
308 308 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
309 309
310 310 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc,tracker:desc'
311 311 assert_response :success
312 312
313 313 trackers = assigns(:issues).map(&:tracker).uniq
314 314 assert_equal [3, 2, 1], trackers.map(&:id)
315 315 end
316 316
317 317 def test_index_with_query_id_and_project_id_should_set_session_query
318 318 get :index, :project_id => 1, :query_id => 4
319 319 assert_response :success
320 320 assert_kind_of Hash, session[:query]
321 321 assert_equal 4, session[:query][:id]
322 322 assert_equal 1, session[:query][:project_id]
323 323 end
324 324
325 325 def test_index_with_invalid_query_id_should_respond_404
326 326 get :index, :project_id => 1, :query_id => 999
327 327 assert_response 404
328 328 end
329 329
330 330 def test_index_with_cross_project_query_in_session_should_show_project_issues
331 331 q = IssueQuery.create!(:name => "test", :user_id => 2, :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
332 332 @request.session[:query] = {:id => q.id, :project_id => 1}
333 333
334 334 with_settings :display_subprojects_issues => '0' do
335 335 get :index, :project_id => 1
336 336 end
337 337 assert_response :success
338 338 assert_not_nil assigns(:query)
339 339 assert_equal q.id, assigns(:query).id
340 340 assert_equal 1, assigns(:query).project_id
341 341 assert_equal [1], assigns(:issues).map(&:project_id).uniq
342 342 end
343 343
344 344 def test_private_query_should_not_be_available_to_other_users
345 345 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
346 346 @request.session[:user_id] = 3
347 347
348 348 get :index, :query_id => q.id
349 349 assert_response 403
350 350 end
351 351
352 352 def test_private_query_should_be_available_to_its_user
353 353 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
354 354 @request.session[:user_id] = 2
355 355
356 356 get :index, :query_id => q.id
357 357 assert_response :success
358 358 end
359 359
360 360 def test_public_query_should_be_available_to_other_users
361 361 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PUBLIC, :project => nil)
362 362 @request.session[:user_id] = 3
363 363
364 364 get :index, :query_id => q.id
365 365 assert_response :success
366 366 end
367 367
368 368 def test_index_should_omit_page_param_in_export_links
369 369 get :index, :page => 2
370 370 assert_response :success
371 371 assert_select 'a.atom[href=/issues.atom]'
372 372 assert_select 'a.csv[href=/issues.csv]'
373 373 assert_select 'a.pdf[href=/issues.pdf]'
374 374 assert_select 'form#csv-export-form[action=/issues.csv]'
375 375 end
376 376
377 377 def test_index_should_not_warn_when_not_exceeding_export_limit
378 378 with_settings :issues_export_limit => 200 do
379 379 get :index
380 380 assert_select '#csv-export-options p.icon-warning', 0
381 381 end
382 382 end
383 383
384 384 def test_index_should_warn_when_exceeding_export_limit
385 385 with_settings :issues_export_limit => 2 do
386 386 get :index
387 387 assert_select '#csv-export-options p.icon-warning', :text => %r{limit: 2}
388 388 end
389 389 end
390 390
391 391 def test_index_csv
392 392 get :index, :format => 'csv'
393 393 assert_response :success
394 394 assert_not_nil assigns(:issues)
395 395 assert_equal 'text/csv; header=present', @response.content_type
396 396 assert @response.body.starts_with?("#,")
397 397 lines = @response.body.chomp.split("\n")
398 398 assert_equal assigns(:query).columns.size, lines[0].split(',').size
399 399 end
400 400
401 401 def test_index_csv_with_project
402 402 get :index, :project_id => 1, :format => 'csv'
403 403 assert_response :success
404 404 assert_not_nil assigns(:issues)
405 405 assert_equal 'text/csv; header=present', @response.content_type
406 406 end
407 407
408 408 def test_index_csv_with_description
409 409 Issue.generate!(:description => 'test_index_csv_with_description')
410 410
411 411 with_settings :default_language => 'en' do
412 412 get :index, :format => 'csv', :description => '1'
413 413 assert_response :success
414 414 assert_not_nil assigns(:issues)
415 415 end
416 416
417 417 assert_equal 'text/csv; header=present', response.content_type
418 418 headers = response.body.chomp.split("\n").first.split(',')
419 419 assert_include 'Description', headers
420 420 assert_include 'test_index_csv_with_description', response.body
421 421 end
422 422
423 423 def test_index_csv_with_spent_time_column
424 424 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
425 425 TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
426 426
427 427 get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
428 428 assert_response :success
429 429 assert_equal 'text/csv; header=present', @response.content_type
430 430 lines = @response.body.chomp.split("\n")
431 431 assert_include "#{issue.id},#{issue.subject},7.33", lines
432 432 end
433 433
434 434 def test_index_csv_with_all_columns
435 435 get :index, :format => 'csv', :columns => 'all'
436 436 assert_response :success
437 437 assert_not_nil assigns(:issues)
438 438 assert_equal 'text/csv; header=present', @response.content_type
439 439 assert_match /\A#,/, response.body
440 440 lines = response.body.chomp.split("\n")
441 441 assert_equal assigns(:query).available_inline_columns.size, lines[0].split(',').size
442 442 end
443 443
444 444 def test_index_csv_with_multi_column_field
445 445 CustomField.find(1).update_attribute :multiple, true
446 446 issue = Issue.find(1)
447 447 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
448 448 issue.save!
449 449
450 450 get :index, :format => 'csv', :columns => 'all'
451 451 assert_response :success
452 452 lines = @response.body.chomp.split("\n")
453 453 assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
454 454 end
455 455
456 456 def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
457 457 field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
458 458 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
459 459
460 460 with_settings :default_language => 'fr' do
461 461 get :index, :format => 'csv', :columns => 'all'
462 462 assert_response :success
463 463 issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
464 464 assert_include '185,60', issue_line
465 465 end
466 466
467 467 with_settings :default_language => 'en' do
468 468 get :index, :format => 'csv', :columns => 'all'
469 469 assert_response :success
470 470 issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
471 471 assert_include '185.60', issue_line
472 472 end
473 473 end
474 474
475 475 def test_index_csv_should_fill_parent_column_with_parent_id
476 476 Issue.delete_all
477 477 parent = Issue.generate!
478 478 child = Issue.generate!(:parent_issue_id => parent.id)
479 479
480 480 with_settings :default_language => 'en' do
481 481 get :index, :format => 'csv', :c => %w(parent)
482 482 end
483 483 lines = response.body.split
484 484 assert_include "#{child.id},#{parent.id}", lines
485 485 end
486 486
487 487 def test_index_csv_big_5
488 488 with_settings :default_language => "zh-TW" do
489 489 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
490 490 str_big5 = "\xa4@\xa4\xeb"
491 491 if str_utf8.respond_to?(:force_encoding)
492 492 str_utf8.force_encoding('UTF-8')
493 493 str_big5.force_encoding('Big5')
494 494 end
495 495 issue = Issue.generate!(:subject => str_utf8)
496 496
497 497 get :index, :project_id => 1,
498 498 :f => ['subject'],
499 499 :op => '=', :values => [str_utf8],
500 500 :format => 'csv'
501 501 assert_equal 'text/csv; header=present', @response.content_type
502 502 lines = @response.body.chomp.split("\n")
503 503 s1 = "\xaa\xac\xbaA"
504 504 if str_utf8.respond_to?(:force_encoding)
505 505 s1.force_encoding('Big5')
506 506 end
507 507 assert_include s1, lines[0]
508 508 assert_include str_big5, lines[1]
509 509 end
510 510 end
511 511
512 512 def test_index_csv_cannot_convert_should_be_replaced_big_5
513 513 with_settings :default_language => "zh-TW" do
514 514 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
515 515 if str_utf8.respond_to?(:force_encoding)
516 516 str_utf8.force_encoding('UTF-8')
517 517 end
518 518 issue = Issue.generate!(:subject => str_utf8)
519 519
520 520 get :index, :project_id => 1,
521 521 :f => ['subject'],
522 522 :op => '=', :values => [str_utf8],
523 523 :c => ['status', 'subject'],
524 524 :format => 'csv',
525 525 :set_filter => 1
526 526 assert_equal 'text/csv; header=present', @response.content_type
527 527 lines = @response.body.chomp.split("\n")
528 528 s1 = "\xaa\xac\xbaA" # status
529 529 if str_utf8.respond_to?(:force_encoding)
530 530 s1.force_encoding('Big5')
531 531 end
532 532 assert lines[0].include?(s1)
533 533 s2 = lines[1].split(",")[2]
534 534 if s1.respond_to?(:force_encoding)
535 535 s3 = "\xa5H?" # subject
536 536 s3.force_encoding('Big5')
537 537 assert_equal s3, s2
538 538 elsif RUBY_PLATFORM == 'java'
539 539 assert_equal "??", s2
540 540 else
541 541 assert_equal "\xa5H???", s2
542 542 end
543 543 end
544 544 end
545 545
546 546 def test_index_csv_tw
547 547 with_settings :default_language => "zh-TW" do
548 548 str1 = "test_index_csv_tw"
549 549 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
550 550
551 551 get :index, :project_id => 1,
552 552 :f => ['subject'],
553 553 :op => '=', :values => [str1],
554 554 :c => ['estimated_hours', 'subject'],
555 555 :format => 'csv',
556 556 :set_filter => 1
557 557 assert_equal 'text/csv; header=present', @response.content_type
558 558 lines = @response.body.chomp.split("\n")
559 559 assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
560 560 end
561 561 end
562 562
563 563 def test_index_csv_fr
564 564 with_settings :default_language => "fr" do
565 565 str1 = "test_index_csv_fr"
566 566 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
567 567
568 568 get :index, :project_id => 1,
569 569 :f => ['subject'],
570 570 :op => '=', :values => [str1],
571 571 :c => ['estimated_hours', 'subject'],
572 572 :format => 'csv',
573 573 :set_filter => 1
574 574 assert_equal 'text/csv; header=present', @response.content_type
575 575 lines = @response.body.chomp.split("\n")
576 576 assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
577 577 end
578 578 end
579 579
580 580 def test_index_pdf
581 581 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
582 582 with_settings :default_language => lang do
583 583
584 584 get :index
585 585 assert_response :success
586 586 assert_template 'index'
587 587
588 588 get :index, :format => 'pdf'
589 589 assert_response :success
590 590 assert_not_nil assigns(:issues)
591 591 assert_equal 'application/pdf', @response.content_type
592 592
593 593 get :index, :project_id => 1, :format => 'pdf'
594 594 assert_response :success
595 595 assert_not_nil assigns(:issues)
596 596 assert_equal 'application/pdf', @response.content_type
597 597
598 598 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
599 599 assert_response :success
600 600 assert_not_nil assigns(:issues)
601 601 assert_equal 'application/pdf', @response.content_type
602 602 end
603 603 end
604 604 end
605 605
606 606 def test_index_pdf_with_query_grouped_by_list_custom_field
607 607 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
608 608 assert_response :success
609 609 assert_not_nil assigns(:issues)
610 610 assert_not_nil assigns(:issue_count_by_group)
611 611 assert_equal 'application/pdf', @response.content_type
612 612 end
613 613
614 614 def test_index_atom
615 615 get :index, :project_id => 'ecookbook', :format => 'atom'
616 616 assert_response :success
617 617 assert_template 'common/feed'
618 618 assert_equal 'application/atom+xml', response.content_type
619 619
620 620 assert_select 'feed' do
621 621 assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
622 622 assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
623 623 assert_select 'entry link[href=?]', 'http://test.host/issues/1'
624 624 end
625 625 end
626 626
627 627 def test_index_sort
628 628 get :index, :sort => 'tracker,id:desc'
629 629 assert_response :success
630 630
631 631 sort_params = @request.session['issues_index_sort']
632 632 assert sort_params.is_a?(String)
633 633 assert_equal 'tracker,id:desc', sort_params
634 634
635 635 issues = assigns(:issues)
636 636 assert_not_nil issues
637 637 assert !issues.empty?
638 638 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
639 639 assert_select 'table.issues.sort-by-tracker.sort-asc'
640 640 end
641 641
642 642 def test_index_sort_by_field_not_included_in_columns
643 643 Setting.issue_list_default_columns = %w(subject author)
644 644 get :index, :sort => 'tracker'
645 645 end
646 646
647 647 def test_index_sort_by_assigned_to
648 648 get :index, :sort => 'assigned_to'
649 649 assert_response :success
650 650 assignees = assigns(:issues).collect(&:assigned_to).compact
651 651 assert_equal assignees.sort, assignees
652 652 assert_select 'table.issues.sort-by-assigned-to.sort-asc'
653 653 end
654 654
655 655 def test_index_sort_by_assigned_to_desc
656 656 get :index, :sort => 'assigned_to:desc'
657 657 assert_response :success
658 658 assignees = assigns(:issues).collect(&:assigned_to).compact
659 659 assert_equal assignees.sort.reverse, assignees
660 660 assert_select 'table.issues.sort-by-assigned-to.sort-desc'
661 661 end
662 662
663 663 def test_index_group_by_assigned_to
664 664 get :index, :group_by => 'assigned_to', :sort => 'priority'
665 665 assert_response :success
666 666 end
667 667
668 668 def test_index_sort_by_author
669 669 get :index, :sort => 'author'
670 670 assert_response :success
671 671 authors = assigns(:issues).collect(&:author)
672 672 assert_equal authors.sort, authors
673 673 end
674 674
675 675 def test_index_sort_by_author_desc
676 676 get :index, :sort => 'author:desc'
677 677 assert_response :success
678 678 authors = assigns(:issues).collect(&:author)
679 679 assert_equal authors.sort.reverse, authors
680 680 end
681 681
682 682 def test_index_group_by_author
683 683 get :index, :group_by => 'author', :sort => 'priority'
684 684 assert_response :success
685 685 end
686 686
687 687 def test_index_sort_by_spent_hours
688 688 get :index, :sort => 'spent_hours:desc'
689 689 assert_response :success
690 690 hours = assigns(:issues).collect(&:spent_hours)
691 691 assert_equal hours.sort.reverse, hours
692 692 end
693 693
694 694 def test_index_sort_by_user_custom_field
695 695 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
696 696 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
697 697 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
698 698 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
699 699 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
700 700
701 701 get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
702 702 assert_response :success
703 703
704 704 assert_equal [2, 3, 1], assigns(:issues).select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
705 705 end
706 706
707 707 def test_index_with_columns
708 708 columns = ['tracker', 'subject', 'assigned_to']
709 709 get :index, :set_filter => 1, :c => columns
710 710 assert_response :success
711 711
712 712 # query should use specified columns
713 713 query = assigns(:query)
714 714 assert_kind_of IssueQuery, query
715 715 assert_equal columns, query.column_names.map(&:to_s)
716 716
717 717 # columns should be stored in session
718 718 assert_kind_of Hash, session[:query]
719 719 assert_kind_of Array, session[:query][:column_names]
720 720 assert_equal columns, session[:query][:column_names].map(&:to_s)
721 721
722 722 # ensure only these columns are kept in the selected columns list
723 723 assert_select 'select#selected_columns option' do
724 724 assert_select 'option', 3
725 725 assert_select 'option[value=tracker]'
726 726 assert_select 'option[value=project]', 0
727 727 end
728 728 end
729 729
730 730 def test_index_without_project_should_implicitly_add_project_column_to_default_columns
731 731 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
732 732 get :index, :set_filter => 1
733 733
734 734 # query should use specified columns
735 735 query = assigns(:query)
736 736 assert_kind_of IssueQuery, query
737 737 assert_equal [:id, :project, :tracker, :subject, :assigned_to], query.columns.map(&:name)
738 738 end
739 739
740 740 def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
741 741 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
742 742 columns = ['id', 'tracker', 'subject', 'assigned_to']
743 743 get :index, :set_filter => 1, :c => columns
744 744
745 745 # query should use specified columns
746 746 query = assigns(:query)
747 747 assert_kind_of IssueQuery, query
748 748 assert_equal columns.map(&:to_sym), query.columns.map(&:name)
749 749 end
750 750
751 751 def test_index_with_custom_field_column
752 752 columns = %w(tracker subject cf_2)
753 753 get :index, :set_filter => 1, :c => columns
754 754 assert_response :success
755 755
756 756 # query should use specified columns
757 757 query = assigns(:query)
758 758 assert_kind_of IssueQuery, query
759 759 assert_equal columns, query.column_names.map(&:to_s)
760 760
761 761 assert_select 'table.issues td.cf_2.string'
762 762 end
763 763
764 764 def test_index_with_multi_custom_field_column
765 765 field = CustomField.find(1)
766 766 field.update_attribute :multiple, true
767 767 issue = Issue.find(1)
768 768 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
769 769 issue.save!
770 770
771 771 get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
772 772 assert_response :success
773 773
774 774 assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
775 775 end
776 776
777 777 def test_index_with_multi_user_custom_field_column
778 778 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
779 779 :tracker_ids => [1], :is_for_all => true)
780 780 issue = Issue.find(1)
781 781 issue.custom_field_values = {field.id => ['2', '3']}
782 782 issue.save!
783 783
784 784 get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
785 785 assert_response :success
786 786
787 787 assert_select "table.issues td.cf_#{field.id}" do
788 788 assert_select 'a', 2
789 789 assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
790 790 assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
791 791 end
792 792 end
793 793
794 794 def test_index_with_date_column
795 795 with_settings :date_format => '%d/%m/%Y' do
796 796 Issue.find(1).update_attribute :start_date, '1987-08-24'
797 797 get :index, :set_filter => 1, :c => %w(start_date)
798 798 assert_select "table.issues td.start_date", :text => '24/08/1987'
799 799 end
800 800 end
801 801
802 802 def test_index_with_done_ratio_column
803 803 Issue.find(1).update_attribute :done_ratio, 40
804 804 get :index, :set_filter => 1, :c => %w(done_ratio)
805 805 assert_select 'table.issues td.done_ratio' do
806 806 assert_select 'table.progress' do
807 807 assert_select 'td.closed[style=?]', 'width: 40%;'
808 808 end
809 809 end
810 810 end
811 811
812 812 def test_index_with_spent_hours_column
813 813 get :index, :set_filter => 1, :c => %w(subject spent_hours)
814 814 assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
815 815 end
816 816
817 817 def test_index_should_not_show_spent_hours_column_without_permission
818 818 Role.anonymous.remove_permission! :view_time_entries
819 819 get :index, :set_filter => 1, :c => %w(subject spent_hours)
820 820 assert_select 'td.spent_hours', 0
821 821 end
822 822
823 823 def test_index_with_fixed_version_column
824 824 get :index, :set_filter => 1, :c => %w(fixed_version)
825 825 assert_select 'table.issues td.fixed_version' do
826 826 assert_select 'a[href=?]', '/versions/2', :text => '1.0'
827 827 end
828 828 end
829 829
830 830 def test_index_with_relations_column
831 831 IssueRelation.delete_all
832 832 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
833 833 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
834 834 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
835 835 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
836 836
837 837 get :index, :set_filter => 1, :c => %w(subject relations)
838 838 assert_response :success
839 839 assert_select "tr#issue-1 td.relations" do
840 840 assert_select "span", 3
841 841 assert_select "span", :text => "Related to #7"
842 842 assert_select "span", :text => "Related to #8"
843 843 assert_select "span", :text => "Blocks #11"
844 844 end
845 845 assert_select "tr#issue-2 td.relations" do
846 846 assert_select "span", 1
847 847 assert_select "span", :text => "Blocked by #12"
848 848 end
849 849 assert_select "tr#issue-3 td.relations" do
850 850 assert_select "span", 0
851 851 end
852 852
853 853 get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
854 854 assert_response :success
855 855 assert_equal 'text/csv; header=present', response.content_type
856 856 lines = response.body.chomp.split("\n")
857 857 assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
858 858 assert_include '2,Blocked by #12', lines
859 859 assert_include '3,""', lines
860 860
861 861 get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
862 862 assert_response :success
863 863 assert_equal 'application/pdf', response.content_type
864 864 end
865 865
866 866 def test_index_with_description_column
867 867 get :index, :set_filter => 1, :c => %w(subject description)
868 868
869 869 assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
870 870 assert_select 'td.description[colspan=3]', :text => 'Unable to print recipes'
871 871
872 872 get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
873 873 assert_response :success
874 874 assert_equal 'application/pdf', response.content_type
875 875 end
876 876
877 def test_index_with_parent_column
878 Issue.delete_all
879 parent = Issue.generate!
880 child = Issue.generate!(:parent_issue_id => parent.id)
881
882 get :index, :c => %w(parent)
883
884 assert_select 'td.parent', :text => "#{parent.tracker} ##{parent.id}"
885 assert_select 'td.parent a[title=?]', parent.subject
886 end
887
877 888 def test_index_send_html_if_query_is_invalid
878 889 get :index, :f => ['start_date'], :op => {:start_date => '='}
879 890 assert_equal 'text/html', @response.content_type
880 891 assert_template 'index'
881 892 end
882 893
883 894 def test_index_send_nothing_if_query_is_invalid
884 895 get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
885 896 assert_equal 'text/csv', @response.content_type
886 897 assert @response.body.blank?
887 898 end
888 899
889 900 def test_show_by_anonymous
890 901 get :show, :id => 1
891 902 assert_response :success
892 903 assert_template 'show'
893 904 assert_equal Issue.find(1), assigns(:issue)
894 905 assert_select 'div.issue div.description', :text => /Unable to print recipes/
895 906 # anonymous role is allowed to add a note
896 907 assert_select 'form#issue-form' do
897 908 assert_select 'fieldset' do
898 909 assert_select 'legend', :text => 'Notes'
899 910 assert_select 'textarea[name=?]', 'issue[notes]'
900 911 end
901 912 end
902 913 assert_select 'title', :text => "Bug #1: #{ESCAPED_UCANT} print recipes - eCookbook - Redmine"
903 914 end
904 915
905 916 def test_show_by_manager
906 917 @request.session[:user_id] = 2
907 918 get :show, :id => 1
908 919 assert_response :success
909 920 assert_select 'a', :text => /Quote/
910 921 assert_select 'form#issue-form' do
911 922 assert_select 'fieldset' do
912 923 assert_select 'legend', :text => 'Change properties'
913 924 assert_select 'input[name=?]', 'issue[subject]'
914 925 end
915 926 assert_select 'fieldset' do
916 927 assert_select 'legend', :text => 'Log time'
917 928 assert_select 'input[name=?]', 'time_entry[hours]'
918 929 end
919 930 assert_select 'fieldset' do
920 931 assert_select 'legend', :text => 'Notes'
921 932 assert_select 'textarea[name=?]', 'issue[notes]'
922 933 end
923 934 end
924 935 end
925 936
926 937 def test_show_should_display_update_form
927 938 @request.session[:user_id] = 2
928 939 get :show, :id => 1
929 940 assert_response :success
930 941
931 942 assert_select 'form#issue-form' do
932 943 assert_select 'input[name=?]', 'issue[is_private]'
933 944 assert_select 'select[name=?]', 'issue[project_id]'
934 945 assert_select 'select[name=?]', 'issue[tracker_id]'
935 946 assert_select 'input[name=?]', 'issue[subject]'
936 947 assert_select 'textarea[name=?]', 'issue[description]'
937 948 assert_select 'select[name=?]', 'issue[status_id]'
938 949 assert_select 'select[name=?]', 'issue[priority_id]'
939 950 assert_select 'select[name=?]', 'issue[assigned_to_id]'
940 951 assert_select 'select[name=?]', 'issue[category_id]'
941 952 assert_select 'select[name=?]', 'issue[fixed_version_id]'
942 953 assert_select 'input[name=?]', 'issue[parent_issue_id]'
943 954 assert_select 'input[name=?]', 'issue[start_date]'
944 955 assert_select 'input[name=?]', 'issue[due_date]'
945 956 assert_select 'select[name=?]', 'issue[done_ratio]'
946 957 assert_select 'input[name=?]', 'issue[custom_field_values][2]'
947 958 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
948 959 assert_select 'textarea[name=?]', 'issue[notes]'
949 960 end
950 961 end
951 962
952 963 def test_show_should_display_update_form_with_minimal_permissions
953 964 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
954 965 WorkflowTransition.delete_all :role_id => 1
955 966
956 967 @request.session[:user_id] = 2
957 968 get :show, :id => 1
958 969 assert_response :success
959 970
960 971 assert_select 'form#issue-form' do
961 972 assert_select 'input[name=?]', 'issue[is_private]', 0
962 973 assert_select 'select[name=?]', 'issue[project_id]', 0
963 974 assert_select 'select[name=?]', 'issue[tracker_id]', 0
964 975 assert_select 'input[name=?]', 'issue[subject]', 0
965 976 assert_select 'textarea[name=?]', 'issue[description]', 0
966 977 assert_select 'select[name=?]', 'issue[status_id]', 0
967 978 assert_select 'select[name=?]', 'issue[priority_id]', 0
968 979 assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
969 980 assert_select 'select[name=?]', 'issue[category_id]', 0
970 981 assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
971 982 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
972 983 assert_select 'input[name=?]', 'issue[start_date]', 0
973 984 assert_select 'input[name=?]', 'issue[due_date]', 0
974 985 assert_select 'select[name=?]', 'issue[done_ratio]', 0
975 986 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
976 987 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
977 988 assert_select 'textarea[name=?]', 'issue[notes]'
978 989 end
979 990 end
980 991
981 992 def test_show_should_display_update_form_with_workflow_permissions
982 993 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
983 994
984 995 @request.session[:user_id] = 2
985 996 get :show, :id => 1
986 997 assert_response :success
987 998
988 999 assert_select 'form#issue-form' do
989 1000 assert_select 'input[name=?]', 'issue[is_private]', 0
990 1001 assert_select 'select[name=?]', 'issue[project_id]', 0
991 1002 assert_select 'select[name=?]', 'issue[tracker_id]', 0
992 1003 assert_select 'input[name=?]', 'issue[subject]', 0
993 1004 assert_select 'textarea[name=?]', 'issue[description]', 0
994 1005 assert_select 'select[name=?]', 'issue[status_id]'
995 1006 assert_select 'select[name=?]', 'issue[priority_id]', 0
996 1007 assert_select 'select[name=?]', 'issue[assigned_to_id]'
997 1008 assert_select 'select[name=?]', 'issue[category_id]', 0
998 1009 assert_select 'select[name=?]', 'issue[fixed_version_id]'
999 1010 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1000 1011 assert_select 'input[name=?]', 'issue[start_date]', 0
1001 1012 assert_select 'input[name=?]', 'issue[due_date]', 0
1002 1013 assert_select 'select[name=?]', 'issue[done_ratio]'
1003 1014 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
1004 1015 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1005 1016 assert_select 'textarea[name=?]', 'issue[notes]'
1006 1017 end
1007 1018 end
1008 1019
1009 1020 def test_show_should_not_display_update_form_without_permissions
1010 1021 Role.find(1).update_attribute :permissions, [:view_issues]
1011 1022
1012 1023 @request.session[:user_id] = 2
1013 1024 get :show, :id => 1
1014 1025 assert_response :success
1015 1026
1016 1027 assert_select 'form#issue-form', 0
1017 1028 end
1018 1029
1019 1030 def test_update_form_should_not_display_inactive_enumerations
1020 1031 assert !IssuePriority.find(15).active?
1021 1032
1022 1033 @request.session[:user_id] = 2
1023 1034 get :show, :id => 1
1024 1035 assert_response :success
1025 1036
1026 1037 assert_select 'form#issue-form' do
1027 1038 assert_select 'select[name=?]', 'issue[priority_id]' do
1028 1039 assert_select 'option[value=4]'
1029 1040 assert_select 'option[value=15]', 0
1030 1041 end
1031 1042 end
1032 1043 end
1033 1044
1034 1045 def test_update_form_should_allow_attachment_upload
1035 1046 @request.session[:user_id] = 2
1036 1047 get :show, :id => 1
1037 1048
1038 1049 assert_select 'form#issue-form[method=post][enctype=multipart/form-data]' do
1039 1050 assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
1040 1051 end
1041 1052 end
1042 1053
1043 1054 def test_show_should_deny_anonymous_access_without_permission
1044 1055 Role.anonymous.remove_permission!(:view_issues)
1045 1056 get :show, :id => 1
1046 1057 assert_response :redirect
1047 1058 end
1048 1059
1049 1060 def test_show_should_deny_anonymous_access_to_private_issue
1050 1061 Issue.where(:id => 1).update_all(["is_private = ?", true])
1051 1062 get :show, :id => 1
1052 1063 assert_response :redirect
1053 1064 end
1054 1065
1055 1066 def test_show_should_deny_non_member_access_without_permission
1056 1067 Role.non_member.remove_permission!(:view_issues)
1057 1068 @request.session[:user_id] = 9
1058 1069 get :show, :id => 1
1059 1070 assert_response 403
1060 1071 end
1061 1072
1062 1073 def test_show_should_deny_non_member_access_to_private_issue
1063 1074 Issue.where(:id => 1).update_all(["is_private = ?", true])
1064 1075 @request.session[:user_id] = 9
1065 1076 get :show, :id => 1
1066 1077 assert_response 403
1067 1078 end
1068 1079
1069 1080 def test_show_should_deny_member_access_without_permission
1070 1081 Role.find(1).remove_permission!(:view_issues)
1071 1082 @request.session[:user_id] = 2
1072 1083 get :show, :id => 1
1073 1084 assert_response 403
1074 1085 end
1075 1086
1076 1087 def test_show_should_deny_member_access_to_private_issue_without_permission
1077 1088 Issue.where(:id => 1).update_all(["is_private = ?", true])
1078 1089 @request.session[:user_id] = 3
1079 1090 get :show, :id => 1
1080 1091 assert_response 403
1081 1092 end
1082 1093
1083 1094 def test_show_should_allow_author_access_to_private_issue
1084 1095 Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
1085 1096 @request.session[:user_id] = 3
1086 1097 get :show, :id => 1
1087 1098 assert_response :success
1088 1099 end
1089 1100
1090 1101 def test_show_should_allow_assignee_access_to_private_issue
1091 1102 Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
1092 1103 @request.session[:user_id] = 3
1093 1104 get :show, :id => 1
1094 1105 assert_response :success
1095 1106 end
1096 1107
1097 1108 def test_show_should_allow_member_access_to_private_issue_with_permission
1098 1109 Issue.where(:id => 1).update_all(["is_private = ?", true])
1099 1110 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
1100 1111 @request.session[:user_id] = 3
1101 1112 get :show, :id => 1
1102 1113 assert_response :success
1103 1114 end
1104 1115
1105 1116 def test_show_should_not_disclose_relations_to_invisible_issues
1106 1117 Setting.cross_project_issue_relations = '1'
1107 1118 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
1108 1119 # Relation to a private project issue
1109 1120 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
1110 1121
1111 1122 get :show, :id => 1
1112 1123 assert_response :success
1113 1124
1114 1125 assert_select 'div#relations' do
1115 1126 assert_select 'a', :text => /#2$/
1116 1127 assert_select 'a', :text => /#4$/, :count => 0
1117 1128 end
1118 1129 end
1119 1130
1120 1131 def test_show_should_list_subtasks
1121 1132 Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1122 1133
1123 1134 get :show, :id => 1
1124 1135 assert_response :success
1125 1136
1126 1137 assert_select 'div#issue_tree' do
1127 1138 assert_select 'td.subject', :text => /Child Issue/
1128 1139 end
1129 1140 end
1130 1141
1131 1142 def test_show_should_list_parents
1132 1143 issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1133 1144
1134 1145 get :show, :id => issue.id
1135 1146 assert_response :success
1136 1147
1137 1148 assert_select 'div.subject' do
1138 1149 assert_select 'h3', 'Child Issue'
1139 1150 assert_select 'a[href=/issues/1]'
1140 1151 end
1141 1152 end
1142 1153
1143 1154 def test_show_should_not_display_prev_next_links_without_query_in_session
1144 1155 get :show, :id => 1
1145 1156 assert_response :success
1146 1157 assert_nil assigns(:prev_issue_id)
1147 1158 assert_nil assigns(:next_issue_id)
1148 1159
1149 1160 assert_select 'div.next-prev-links', 0
1150 1161 end
1151 1162
1152 1163 def test_show_should_display_prev_next_links_with_query_in_session
1153 1164 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1154 1165 @request.session['issues_index_sort'] = 'id'
1155 1166
1156 1167 with_settings :display_subprojects_issues => '0' do
1157 1168 get :show, :id => 3
1158 1169 end
1159 1170
1160 1171 assert_response :success
1161 1172 # Previous and next issues for all projects
1162 1173 assert_equal 2, assigns(:prev_issue_id)
1163 1174 assert_equal 5, assigns(:next_issue_id)
1164 1175
1165 1176 count = Issue.open.visible.count
1166 1177
1167 1178 assert_select 'div.next-prev-links' do
1168 1179 assert_select 'a[href=/issues/2]', :text => /Previous/
1169 1180 assert_select 'a[href=/issues/5]', :text => /Next/
1170 1181 assert_select 'span.position', :text => "3 of #{count}"
1171 1182 end
1172 1183 end
1173 1184
1174 1185 def test_show_should_display_prev_next_links_with_saved_query_in_session
1175 1186 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1,
1176 1187 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1177 1188 :sort_criteria => [['id', 'asc']])
1178 1189 @request.session[:query] = {:id => query.id, :project_id => nil}
1179 1190
1180 1191 get :show, :id => 11
1181 1192
1182 1193 assert_response :success
1183 1194 assert_equal query, assigns(:query)
1184 1195 # Previous and next issues for all projects
1185 1196 assert_equal 8, assigns(:prev_issue_id)
1186 1197 assert_equal 12, assigns(:next_issue_id)
1187 1198
1188 1199 assert_select 'div.next-prev-links' do
1189 1200 assert_select 'a[href=/issues/8]', :text => /Previous/
1190 1201 assert_select 'a[href=/issues/12]', :text => /Next/
1191 1202 end
1192 1203 end
1193 1204
1194 1205 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1195 1206 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1196 1207
1197 1208 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1198 1209 @request.session['issues_index_sort'] = assoc_sort
1199 1210
1200 1211 get :show, :id => 3
1201 1212 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1202 1213
1203 1214 assert_select 'div.next-prev-links' do
1204 1215 assert_select 'a', :text => /(Previous|Next)/
1205 1216 end
1206 1217 end
1207 1218 end
1208 1219
1209 1220 def test_show_should_display_prev_next_links_with_project_query_in_session
1210 1221 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1211 1222 @request.session['issues_index_sort'] = 'id'
1212 1223
1213 1224 with_settings :display_subprojects_issues => '0' do
1214 1225 get :show, :id => 3
1215 1226 end
1216 1227
1217 1228 assert_response :success
1218 1229 # Previous and next issues inside project
1219 1230 assert_equal 2, assigns(:prev_issue_id)
1220 1231 assert_equal 7, assigns(:next_issue_id)
1221 1232
1222 1233 assert_select 'div.next-prev-links' do
1223 1234 assert_select 'a[href=/issues/2]', :text => /Previous/
1224 1235 assert_select 'a[href=/issues/7]', :text => /Next/
1225 1236 end
1226 1237 end
1227 1238
1228 1239 def test_show_should_not_display_prev_link_for_first_issue
1229 1240 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1230 1241 @request.session['issues_index_sort'] = 'id'
1231 1242
1232 1243 with_settings :display_subprojects_issues => '0' do
1233 1244 get :show, :id => 1
1234 1245 end
1235 1246
1236 1247 assert_response :success
1237 1248 assert_nil assigns(:prev_issue_id)
1238 1249 assert_equal 2, assigns(:next_issue_id)
1239 1250
1240 1251 assert_select 'div.next-prev-links' do
1241 1252 assert_select 'a', :text => /Previous/, :count => 0
1242 1253 assert_select 'a[href=/issues/2]', :text => /Next/
1243 1254 end
1244 1255 end
1245 1256
1246 1257 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1247 1258 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1248 1259 @request.session['issues_index_sort'] = 'id'
1249 1260
1250 1261 get :show, :id => 1
1251 1262
1252 1263 assert_response :success
1253 1264 assert_nil assigns(:prev_issue_id)
1254 1265 assert_nil assigns(:next_issue_id)
1255 1266
1256 1267 assert_select 'a', :text => /Previous/, :count => 0
1257 1268 assert_select 'a', :text => /Next/, :count => 0
1258 1269 end
1259 1270
1260 1271 def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
1261 1272 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
1262 1273 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
1263 1274 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
1264 1275 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
1265 1276 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
1266 1277
1267 1278 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1, :filters => {},
1268 1279 :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
1269 1280 @request.session[:query] = {:id => query.id, :project_id => nil}
1270 1281
1271 1282 get :show, :id => 3
1272 1283 assert_response :success
1273 1284
1274 1285 assert_equal 2, assigns(:prev_issue_id)
1275 1286 assert_equal 1, assigns(:next_issue_id)
1276 1287
1277 1288 assert_select 'div.next-prev-links' do
1278 1289 assert_select 'a[href=/issues/2]', :text => /Previous/
1279 1290 assert_select 'a[href=/issues/1]', :text => /Next/
1280 1291 end
1281 1292 end
1282 1293
1283 1294 def test_show_should_display_link_to_the_assignee
1284 1295 get :show, :id => 2
1285 1296 assert_response :success
1286 1297 assert_select '.assigned-to' do
1287 1298 assert_select 'a[href=/users/3]'
1288 1299 end
1289 1300 end
1290 1301
1291 1302 def test_show_should_display_visible_changesets_from_other_projects
1292 1303 project = Project.find(2)
1293 1304 issue = project.issues.first
1294 1305 issue.changeset_ids = [102]
1295 1306 issue.save!
1296 1307 # changesets from other projects should be displayed even if repository
1297 1308 # is disabled on issue's project
1298 1309 project.disable_module! :repository
1299 1310
1300 1311 @request.session[:user_id] = 2
1301 1312 get :show, :id => issue.id
1302 1313
1303 1314 assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
1304 1315 end
1305 1316
1306 1317 def test_show_should_display_watchers
1307 1318 @request.session[:user_id] = 2
1308 1319 Issue.find(1).add_watcher User.find(2)
1309 1320
1310 1321 get :show, :id => 1
1311 1322 assert_select 'div#watchers ul' do
1312 1323 assert_select 'li' do
1313 1324 assert_select 'a[href=/users/2]'
1314 1325 assert_select 'a img[alt=Delete]'
1315 1326 end
1316 1327 end
1317 1328 end
1318 1329
1319 1330 def test_show_should_display_watchers_with_gravatars
1320 1331 @request.session[:user_id] = 2
1321 1332 Issue.find(1).add_watcher User.find(2)
1322 1333
1323 1334 with_settings :gravatar_enabled => '1' do
1324 1335 get :show, :id => 1
1325 1336 end
1326 1337
1327 1338 assert_select 'div#watchers ul' do
1328 1339 assert_select 'li' do
1329 1340 assert_select 'img.gravatar'
1330 1341 assert_select 'a[href=/users/2]'
1331 1342 assert_select 'a img[alt=Delete]'
1332 1343 end
1333 1344 end
1334 1345 end
1335 1346
1336 1347 def test_show_with_thumbnails_enabled_should_display_thumbnails
1337 1348 @request.session[:user_id] = 2
1338 1349
1339 1350 with_settings :thumbnails_enabled => '1' do
1340 1351 get :show, :id => 14
1341 1352 assert_response :success
1342 1353 end
1343 1354
1344 1355 assert_select 'div.thumbnails' do
1345 1356 assert_select 'a[href=/attachments/16/testfile.png]' do
1346 1357 assert_select 'img[src=/attachments/thumbnail/16]'
1347 1358 end
1348 1359 end
1349 1360 end
1350 1361
1351 1362 def test_show_with_thumbnails_disabled_should_not_display_thumbnails
1352 1363 @request.session[:user_id] = 2
1353 1364
1354 1365 with_settings :thumbnails_enabled => '0' do
1355 1366 get :show, :id => 14
1356 1367 assert_response :success
1357 1368 end
1358 1369
1359 1370 assert_select 'div.thumbnails', 0
1360 1371 end
1361 1372
1362 1373 def test_show_with_multi_custom_field
1363 1374 field = CustomField.find(1)
1364 1375 field.update_attribute :multiple, true
1365 1376 issue = Issue.find(1)
1366 1377 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1367 1378 issue.save!
1368 1379
1369 1380 get :show, :id => 1
1370 1381 assert_response :success
1371 1382
1372 1383 assert_select 'td', :text => 'MySQL, Oracle'
1373 1384 end
1374 1385
1375 1386 def test_show_with_multi_user_custom_field
1376 1387 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1377 1388 :tracker_ids => [1], :is_for_all => true)
1378 1389 issue = Issue.find(1)
1379 1390 issue.custom_field_values = {field.id => ['2', '3']}
1380 1391 issue.save!
1381 1392
1382 1393 get :show, :id => 1
1383 1394 assert_response :success
1384 1395
1385 1396 assert_select "td.cf_#{field.id}", :text => 'Dave Lopper, John Smith' do
1386 1397 assert_select 'a', :text => 'Dave Lopper'
1387 1398 assert_select 'a', :text => 'John Smith'
1388 1399 end
1389 1400 end
1390 1401
1391 1402 def test_show_should_display_private_notes_with_permission_only
1392 1403 journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
1393 1404 @request.session[:user_id] = 2
1394 1405
1395 1406 get :show, :id => 2
1396 1407 assert_response :success
1397 1408 assert_include journal, assigns(:journals)
1398 1409
1399 1410 Role.find(1).remove_permission! :view_private_notes
1400 1411 get :show, :id => 2
1401 1412 assert_response :success
1402 1413 assert_not_include journal, assigns(:journals)
1403 1414 end
1404 1415
1405 1416 def test_show_atom
1406 1417 get :show, :id => 2, :format => 'atom'
1407 1418 assert_response :success
1408 1419 assert_template 'journals/index'
1409 1420 # Inline image
1410 1421 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1411 1422 end
1412 1423
1413 1424 def test_show_export_to_pdf
1414 1425 issue = Issue.find(3)
1415 1426 assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1416 1427 get :show, :id => 3, :format => 'pdf'
1417 1428 assert_response :success
1418 1429 assert_equal 'application/pdf', @response.content_type
1419 1430 assert @response.body.starts_with?('%PDF')
1420 1431 assert_not_nil assigns(:issue)
1421 1432 end
1422 1433
1423 1434 def test_export_to_pdf_with_utf8_u_fffd
1424 1435 # U+FFFD
1425 1436 s = "\xef\xbf\xbd"
1426 1437 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
1427 1438 issue = Issue.generate!(:subject => s)
1428 1439 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
1429 1440 with_settings :default_language => lang do
1430 1441 get :show, :id => issue.id, :format => 'pdf'
1431 1442 assert_response :success
1432 1443 assert_equal 'application/pdf', @response.content_type
1433 1444 assert @response.body.starts_with?('%PDF')
1434 1445 assert_not_nil assigns(:issue)
1435 1446 end
1436 1447 end
1437 1448 end
1438 1449
1439 1450 def test_show_export_to_pdf_with_ancestors
1440 1451 issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1441 1452
1442 1453 get :show, :id => issue.id, :format => 'pdf'
1443 1454 assert_response :success
1444 1455 assert_equal 'application/pdf', @response.content_type
1445 1456 assert @response.body.starts_with?('%PDF')
1446 1457 end
1447 1458
1448 1459 def test_show_export_to_pdf_with_descendants
1449 1460 c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1450 1461 c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1451 1462 c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
1452 1463
1453 1464 get :show, :id => 1, :format => 'pdf'
1454 1465 assert_response :success
1455 1466 assert_equal 'application/pdf', @response.content_type
1456 1467 assert @response.body.starts_with?('%PDF')
1457 1468 end
1458 1469
1459 1470 def test_show_export_to_pdf_with_journals
1460 1471 get :show, :id => 1, :format => 'pdf'
1461 1472 assert_response :success
1462 1473 assert_equal 'application/pdf', @response.content_type
1463 1474 assert @response.body.starts_with?('%PDF')
1464 1475 end
1465 1476
1466 1477 def test_show_export_to_pdf_with_changesets
1467 1478 [[100], [100, 101], [100, 101, 102]].each do |cs|
1468 1479 issue1 = Issue.find(3)
1469 1480 issue1.changesets = Changeset.find(cs)
1470 1481 issue1.save!
1471 1482 issue = Issue.find(3)
1472 1483 assert_equal issue.changesets.count, cs.size
1473 1484 get :show, :id => 3, :format => 'pdf'
1474 1485 assert_response :success
1475 1486 assert_equal 'application/pdf', @response.content_type
1476 1487 assert @response.body.starts_with?('%PDF')
1477 1488 end
1478 1489 end
1479 1490
1480 1491 def test_show_invalid_should_respond_with_404
1481 1492 get :show, :id => 999
1482 1493 assert_response 404
1483 1494 end
1484 1495
1485 1496 def test_get_new
1486 1497 @request.session[:user_id] = 2
1487 1498 get :new, :project_id => 1, :tracker_id => 1
1488 1499 assert_response :success
1489 1500 assert_template 'new'
1490 1501
1491 1502 assert_select 'form#issue-form' do
1492 1503 assert_select 'input[name=?]', 'issue[is_private]'
1493 1504 assert_select 'select[name=?]', 'issue[project_id]', 0
1494 1505 assert_select 'select[name=?]', 'issue[tracker_id]'
1495 1506 assert_select 'input[name=?]', 'issue[subject]'
1496 1507 assert_select 'textarea[name=?]', 'issue[description]'
1497 1508 assert_select 'select[name=?]', 'issue[status_id]'
1498 1509 assert_select 'select[name=?]', 'issue[priority_id]'
1499 1510 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1500 1511 assert_select 'select[name=?]', 'issue[category_id]'
1501 1512 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1502 1513 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1503 1514 assert_select 'input[name=?]', 'issue[start_date]'
1504 1515 assert_select 'input[name=?]', 'issue[due_date]'
1505 1516 assert_select 'select[name=?]', 'issue[done_ratio]'
1506 1517 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1507 1518 assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
1508 1519 end
1509 1520
1510 1521 # Be sure we don't display inactive IssuePriorities
1511 1522 assert ! IssuePriority.find(15).active?
1512 1523 assert_select 'select[name=?]', 'issue[priority_id]' do
1513 1524 assert_select 'option[value=15]', 0
1514 1525 end
1515 1526 end
1516 1527
1517 1528 def test_get_new_with_minimal_permissions
1518 1529 Role.find(1).update_attribute :permissions, [:add_issues]
1519 1530 WorkflowTransition.delete_all :role_id => 1
1520 1531
1521 1532 @request.session[:user_id] = 2
1522 1533 get :new, :project_id => 1, :tracker_id => 1
1523 1534 assert_response :success
1524 1535 assert_template 'new'
1525 1536
1526 1537 assert_select 'form#issue-form' do
1527 1538 assert_select 'input[name=?]', 'issue[is_private]', 0
1528 1539 assert_select 'select[name=?]', 'issue[project_id]', 0
1529 1540 assert_select 'select[name=?]', 'issue[tracker_id]'
1530 1541 assert_select 'input[name=?]', 'issue[subject]'
1531 1542 assert_select 'textarea[name=?]', 'issue[description]'
1532 1543 assert_select 'select[name=?]', 'issue[status_id]'
1533 1544 assert_select 'select[name=?]', 'issue[priority_id]'
1534 1545 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1535 1546 assert_select 'select[name=?]', 'issue[category_id]'
1536 1547 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1537 1548 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1538 1549 assert_select 'input[name=?]', 'issue[start_date]'
1539 1550 assert_select 'input[name=?]', 'issue[due_date]'
1540 1551 assert_select 'select[name=?]', 'issue[done_ratio]'
1541 1552 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1542 1553 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1543 1554 end
1544 1555 end
1545 1556
1546 1557 def test_get_new_with_list_custom_field
1547 1558 @request.session[:user_id] = 2
1548 1559 get :new, :project_id => 1, :tracker_id => 1
1549 1560 assert_response :success
1550 1561 assert_template 'new'
1551 1562
1552 1563 assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
1553 1564 assert_select 'option', 4
1554 1565 assert_select 'option[value=MySQL]', :text => 'MySQL'
1555 1566 end
1556 1567 end
1557 1568
1558 1569 def test_get_new_with_multi_custom_field
1559 1570 field = IssueCustomField.find(1)
1560 1571 field.update_attribute :multiple, true
1561 1572
1562 1573 @request.session[:user_id] = 2
1563 1574 get :new, :project_id => 1, :tracker_id => 1
1564 1575 assert_response :success
1565 1576 assert_template 'new'
1566 1577
1567 1578 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
1568 1579 assert_select 'option', 3
1569 1580 assert_select 'option[value=MySQL]', :text => 'MySQL'
1570 1581 end
1571 1582 assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
1572 1583 end
1573 1584
1574 1585 def test_get_new_with_multi_user_custom_field
1575 1586 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1576 1587 :tracker_ids => [1], :is_for_all => true)
1577 1588
1578 1589 @request.session[:user_id] = 2
1579 1590 get :new, :project_id => 1, :tracker_id => 1
1580 1591 assert_response :success
1581 1592 assert_template 'new'
1582 1593
1583 1594 assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
1584 1595 assert_select 'option', Project.find(1).users.count
1585 1596 assert_select 'option[value=2]', :text => 'John Smith'
1586 1597 end
1587 1598 assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
1588 1599 end
1589 1600
1590 1601 def test_get_new_with_date_custom_field
1591 1602 field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
1592 1603
1593 1604 @request.session[:user_id] = 2
1594 1605 get :new, :project_id => 1, :tracker_id => 1
1595 1606 assert_response :success
1596 1607
1597 1608 assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
1598 1609 end
1599 1610
1600 1611 def test_get_new_with_text_custom_field
1601 1612 field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
1602 1613
1603 1614 @request.session[:user_id] = 2
1604 1615 get :new, :project_id => 1, :tracker_id => 1
1605 1616 assert_response :success
1606 1617
1607 1618 assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
1608 1619 end
1609 1620
1610 1621 def test_get_new_without_default_start_date_is_creation_date
1611 1622 with_settings :default_issue_start_date_to_creation_date => 0 do
1612 1623 @request.session[:user_id] = 2
1613 1624 get :new, :project_id => 1, :tracker_id => 1
1614 1625 assert_response :success
1615 1626 assert_template 'new'
1616 1627 assert_select 'input[name=?]', 'issue[start_date]'
1617 1628 assert_select 'input[name=?][value]', 'issue[start_date]', 0
1618 1629 end
1619 1630 end
1620 1631
1621 1632 def test_get_new_with_default_start_date_is_creation_date
1622 1633 with_settings :default_issue_start_date_to_creation_date => 1 do
1623 1634 @request.session[:user_id] = 2
1624 1635 get :new, :project_id => 1, :tracker_id => 1
1625 1636 assert_response :success
1626 1637 assert_template 'new'
1627 1638 assert_select 'input[name=?][value=?]', 'issue[start_date]',
1628 1639 Date.today.to_s
1629 1640 end
1630 1641 end
1631 1642
1632 1643 def test_get_new_form_should_allow_attachment_upload
1633 1644 @request.session[:user_id] = 2
1634 1645 get :new, :project_id => 1, :tracker_id => 1
1635 1646
1636 1647 assert_select 'form[id=issue-form][method=post][enctype=multipart/form-data]' do
1637 1648 assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
1638 1649 end
1639 1650 end
1640 1651
1641 1652 def test_get_new_should_prefill_the_form_from_params
1642 1653 @request.session[:user_id] = 2
1643 1654 get :new, :project_id => 1,
1644 1655 :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
1645 1656
1646 1657 issue = assigns(:issue)
1647 1658 assert_equal 3, issue.tracker_id
1648 1659 assert_equal 'Prefilled', issue.description
1649 1660 assert_equal 'Custom field value', issue.custom_field_value(2)
1650 1661
1651 1662 assert_select 'select[name=?]', 'issue[tracker_id]' do
1652 1663 assert_select 'option[value=3][selected=selected]'
1653 1664 end
1654 1665 assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
1655 1666 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
1656 1667 end
1657 1668
1658 1669 def test_get_new_should_mark_required_fields
1659 1670 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1660 1671 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1661 1672 WorkflowPermission.delete_all
1662 1673 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
1663 1674 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
1664 1675 @request.session[:user_id] = 2
1665 1676
1666 1677 get :new, :project_id => 1
1667 1678 assert_response :success
1668 1679 assert_template 'new'
1669 1680
1670 1681 assert_select 'label[for=issue_start_date]' do
1671 1682 assert_select 'span[class=required]', 0
1672 1683 end
1673 1684 assert_select 'label[for=issue_due_date]' do
1674 1685 assert_select 'span[class=required]'
1675 1686 end
1676 1687 assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
1677 1688 assert_select 'span[class=required]', 0
1678 1689 end
1679 1690 assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
1680 1691 assert_select 'span[class=required]'
1681 1692 end
1682 1693 end
1683 1694
1684 1695 def test_get_new_should_not_display_readonly_fields
1685 1696 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1686 1697 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1687 1698 WorkflowPermission.delete_all
1688 1699 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
1689 1700 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
1690 1701 @request.session[:user_id] = 2
1691 1702
1692 1703 get :new, :project_id => 1
1693 1704 assert_response :success
1694 1705 assert_template 'new'
1695 1706
1696 1707 assert_select 'input[name=?]', 'issue[start_date]'
1697 1708 assert_select 'input[name=?]', 'issue[due_date]', 0
1698 1709 assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
1699 1710 assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
1700 1711 end
1701 1712
1702 1713 def test_get_new_without_tracker_id
1703 1714 @request.session[:user_id] = 2
1704 1715 get :new, :project_id => 1
1705 1716 assert_response :success
1706 1717 assert_template 'new'
1707 1718
1708 1719 issue = assigns(:issue)
1709 1720 assert_not_nil issue
1710 1721 assert_equal Project.find(1).trackers.first, issue.tracker
1711 1722 end
1712 1723
1713 1724 def test_get_new_with_no_default_status_should_display_an_error
1714 1725 @request.session[:user_id] = 2
1715 1726 IssueStatus.delete_all
1716 1727
1717 1728 get :new, :project_id => 1
1718 1729 assert_response 500
1719 1730 assert_error_tag :content => /No default issue/
1720 1731 end
1721 1732
1722 1733 def test_get_new_with_no_tracker_should_display_an_error
1723 1734 @request.session[:user_id] = 2
1724 1735 Tracker.delete_all
1725 1736
1726 1737 get :new, :project_id => 1
1727 1738 assert_response 500
1728 1739 assert_error_tag :content => /No tracker/
1729 1740 end
1730 1741
1731 1742 def test_update_form_for_new_issue
1732 1743 @request.session[:user_id] = 2
1733 1744 xhr :post, :update_form, :project_id => 1,
1734 1745 :issue => {:tracker_id => 2,
1735 1746 :subject => 'This is the test_new issue',
1736 1747 :description => 'This is the description',
1737 1748 :priority_id => 5}
1738 1749 assert_response :success
1739 1750 assert_template 'update_form'
1740 1751 assert_template :partial => '_form'
1741 1752 assert_equal 'text/javascript', response.content_type
1742 1753
1743 1754 issue = assigns(:issue)
1744 1755 assert_kind_of Issue, issue
1745 1756 assert_equal 1, issue.project_id
1746 1757 assert_equal 2, issue.tracker_id
1747 1758 assert_equal 'This is the test_new issue', issue.subject
1748 1759 end
1749 1760
1750 1761 def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
1751 1762 @request.session[:user_id] = 2
1752 1763 WorkflowTransition.delete_all
1753 1764 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
1754 1765 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5)
1755 1766 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
1756 1767
1757 1768 xhr :post, :update_form, :project_id => 1,
1758 1769 :issue => {:tracker_id => 1,
1759 1770 :status_id => 5,
1760 1771 :subject => 'This is an issue'}
1761 1772
1762 1773 assert_equal 5, assigns(:issue).status_id
1763 1774 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
1764 1775 end
1765 1776
1766 1777 def test_post_create
1767 1778 @request.session[:user_id] = 2
1768 1779 assert_difference 'Issue.count' do
1769 1780 post :create, :project_id => 1,
1770 1781 :issue => {:tracker_id => 3,
1771 1782 :status_id => 2,
1772 1783 :subject => 'This is the test_new issue',
1773 1784 :description => 'This is the description',
1774 1785 :priority_id => 5,
1775 1786 :start_date => '2010-11-07',
1776 1787 :estimated_hours => '',
1777 1788 :custom_field_values => {'2' => 'Value for field 2'}}
1778 1789 end
1779 1790 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1780 1791
1781 1792 issue = Issue.find_by_subject('This is the test_new issue')
1782 1793 assert_not_nil issue
1783 1794 assert_equal 2, issue.author_id
1784 1795 assert_equal 3, issue.tracker_id
1785 1796 assert_equal 2, issue.status_id
1786 1797 assert_equal Date.parse('2010-11-07'), issue.start_date
1787 1798 assert_nil issue.estimated_hours
1788 1799 v = issue.custom_values.where(:custom_field_id => 2).first
1789 1800 assert_not_nil v
1790 1801 assert_equal 'Value for field 2', v.value
1791 1802 end
1792 1803
1793 1804 def test_post_new_with_group_assignment
1794 1805 group = Group.find(11)
1795 1806 project = Project.find(1)
1796 1807 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
1797 1808
1798 1809 with_settings :issue_group_assignment => '1' do
1799 1810 @request.session[:user_id] = 2
1800 1811 assert_difference 'Issue.count' do
1801 1812 post :create, :project_id => project.id,
1802 1813 :issue => {:tracker_id => 3,
1803 1814 :status_id => 1,
1804 1815 :subject => 'This is the test_new_with_group_assignment issue',
1805 1816 :assigned_to_id => group.id}
1806 1817 end
1807 1818 end
1808 1819 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1809 1820
1810 1821 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
1811 1822 assert_not_nil issue
1812 1823 assert_equal group, issue.assigned_to
1813 1824 end
1814 1825
1815 1826 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
1816 1827 with_settings :default_issue_start_date_to_creation_date => 0 do
1817 1828 @request.session[:user_id] = 2
1818 1829 assert_difference 'Issue.count' do
1819 1830 post :create, :project_id => 1,
1820 1831 :issue => {:tracker_id => 3,
1821 1832 :status_id => 2,
1822 1833 :subject => 'This is the test_new issue',
1823 1834 :description => 'This is the description',
1824 1835 :priority_id => 5,
1825 1836 :estimated_hours => '',
1826 1837 :custom_field_values => {'2' => 'Value for field 2'}}
1827 1838 end
1828 1839 assert_redirected_to :controller => 'issues', :action => 'show',
1829 1840 :id => Issue.last.id
1830 1841 issue = Issue.find_by_subject('This is the test_new issue')
1831 1842 assert_not_nil issue
1832 1843 assert_nil issue.start_date
1833 1844 end
1834 1845 end
1835 1846
1836 1847 def test_post_create_without_start_date_and_default_start_date_is_creation_date
1837 1848 with_settings :default_issue_start_date_to_creation_date => 1 do
1838 1849 @request.session[:user_id] = 2
1839 1850 assert_difference 'Issue.count' do
1840 1851 post :create, :project_id => 1,
1841 1852 :issue => {:tracker_id => 3,
1842 1853 :status_id => 2,
1843 1854 :subject => 'This is the test_new issue',
1844 1855 :description => 'This is the description',
1845 1856 :priority_id => 5,
1846 1857 :estimated_hours => '',
1847 1858 :custom_field_values => {'2' => 'Value for field 2'}}
1848 1859 end
1849 1860 assert_redirected_to :controller => 'issues', :action => 'show',
1850 1861 :id => Issue.last.id
1851 1862 issue = Issue.find_by_subject('This is the test_new issue')
1852 1863 assert_not_nil issue
1853 1864 assert_equal Date.today, issue.start_date
1854 1865 end
1855 1866 end
1856 1867
1857 1868 def test_post_create_and_continue
1858 1869 @request.session[:user_id] = 2
1859 1870 assert_difference 'Issue.count' do
1860 1871 post :create, :project_id => 1,
1861 1872 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
1862 1873 :continue => ''
1863 1874 end
1864 1875
1865 1876 issue = Issue.order('id DESC').first
1866 1877 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
1867 1878 assert_not_nil flash[:notice], "flash was not set"
1868 1879 assert_include %|<a href="/issues/#{issue.id}" title="This is first issue">##{issue.id}</a>|, flash[:notice], "issue link not found in the flash message"
1869 1880 end
1870 1881
1871 1882 def test_post_create_without_custom_fields_param
1872 1883 @request.session[:user_id] = 2
1873 1884 assert_difference 'Issue.count' do
1874 1885 post :create, :project_id => 1,
1875 1886 :issue => {:tracker_id => 1,
1876 1887 :subject => 'This is the test_new issue',
1877 1888 :description => 'This is the description',
1878 1889 :priority_id => 5}
1879 1890 end
1880 1891 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1881 1892 end
1882 1893
1883 1894 def test_post_create_with_multi_custom_field
1884 1895 field = IssueCustomField.find_by_name('Database')
1885 1896 field.update_attribute(:multiple, true)
1886 1897
1887 1898 @request.session[:user_id] = 2
1888 1899 assert_difference 'Issue.count' do
1889 1900 post :create, :project_id => 1,
1890 1901 :issue => {:tracker_id => 1,
1891 1902 :subject => 'This is the test_new issue',
1892 1903 :description => 'This is the description',
1893 1904 :priority_id => 5,
1894 1905 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
1895 1906 end
1896 1907 assert_response 302
1897 1908 issue = Issue.order('id DESC').first
1898 1909 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
1899 1910 end
1900 1911
1901 1912 def test_post_create_with_empty_multi_custom_field
1902 1913 field = IssueCustomField.find_by_name('Database')
1903 1914 field.update_attribute(:multiple, true)
1904 1915
1905 1916 @request.session[:user_id] = 2
1906 1917 assert_difference 'Issue.count' do
1907 1918 post :create, :project_id => 1,
1908 1919 :issue => {:tracker_id => 1,
1909 1920 :subject => 'This is the test_new issue',
1910 1921 :description => 'This is the description',
1911 1922 :priority_id => 5,
1912 1923 :custom_field_values => {'1' => ['']}}
1913 1924 end
1914 1925 assert_response 302
1915 1926 issue = Issue.order('id DESC').first
1916 1927 assert_equal [''], issue.custom_field_value(1).sort
1917 1928 end
1918 1929
1919 1930 def test_post_create_with_multi_user_custom_field
1920 1931 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1921 1932 :tracker_ids => [1], :is_for_all => true)
1922 1933
1923 1934 @request.session[:user_id] = 2
1924 1935 assert_difference 'Issue.count' do
1925 1936 post :create, :project_id => 1,
1926 1937 :issue => {:tracker_id => 1,
1927 1938 :subject => 'This is the test_new issue',
1928 1939 :description => 'This is the description',
1929 1940 :priority_id => 5,
1930 1941 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
1931 1942 end
1932 1943 assert_response 302
1933 1944 issue = Issue.order('id DESC').first
1934 1945 assert_equal ['2', '3'], issue.custom_field_value(field).sort
1935 1946 end
1936 1947
1937 1948 def test_post_create_with_required_custom_field_and_without_custom_fields_param
1938 1949 field = IssueCustomField.find_by_name('Database')
1939 1950 field.update_attribute(:is_required, true)
1940 1951
1941 1952 @request.session[:user_id] = 2
1942 1953 assert_no_difference 'Issue.count' do
1943 1954 post :create, :project_id => 1,
1944 1955 :issue => {:tracker_id => 1,
1945 1956 :subject => 'This is the test_new issue',
1946 1957 :description => 'This is the description',
1947 1958 :priority_id => 5}
1948 1959 end
1949 1960 assert_response :success
1950 1961 assert_template 'new'
1951 1962 issue = assigns(:issue)
1952 1963 assert_not_nil issue
1953 1964 assert_error_tag :content => /Database #{ESCAPED_CANT} be blank/
1954 1965 end
1955 1966
1956 1967 def test_create_should_validate_required_fields
1957 1968 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1958 1969 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1959 1970 WorkflowPermission.delete_all
1960 1971 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
1961 1972 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
1962 1973 @request.session[:user_id] = 2
1963 1974
1964 1975 assert_no_difference 'Issue.count' do
1965 1976 post :create, :project_id => 1, :issue => {
1966 1977 :tracker_id => 2,
1967 1978 :status_id => 1,
1968 1979 :subject => 'Test',
1969 1980 :start_date => '',
1970 1981 :due_date => '',
1971 1982 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
1972 1983 }
1973 1984 assert_response :success
1974 1985 assert_template 'new'
1975 1986 end
1976 1987
1977 1988 assert_error_tag :content => /Due date #{ESCAPED_CANT} be blank/i
1978 1989 assert_error_tag :content => /Bar #{ESCAPED_CANT} be blank/i
1979 1990 end
1980 1991
1981 1992 def test_create_should_ignore_readonly_fields
1982 1993 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1983 1994 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1984 1995 WorkflowPermission.delete_all
1985 1996 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
1986 1997 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
1987 1998 @request.session[:user_id] = 2
1988 1999
1989 2000 assert_difference 'Issue.count' do
1990 2001 post :create, :project_id => 1, :issue => {
1991 2002 :tracker_id => 2,
1992 2003 :status_id => 1,
1993 2004 :subject => 'Test',
1994 2005 :start_date => '2012-07-14',
1995 2006 :due_date => '2012-07-16',
1996 2007 :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
1997 2008 }
1998 2009 assert_response 302
1999 2010 end
2000 2011
2001 2012 issue = Issue.order('id DESC').first
2002 2013 assert_equal Date.parse('2012-07-14'), issue.start_date
2003 2014 assert_nil issue.due_date
2004 2015 assert_equal 'value1', issue.custom_field_value(cf1)
2005 2016 assert_nil issue.custom_field_value(cf2)
2006 2017 end
2007 2018
2008 2019 def test_post_create_with_watchers
2009 2020 @request.session[:user_id] = 2
2010 2021 ActionMailer::Base.deliveries.clear
2011 2022
2012 2023 assert_difference 'Watcher.count', 2 do
2013 2024 post :create, :project_id => 1,
2014 2025 :issue => {:tracker_id => 1,
2015 2026 :subject => 'This is a new issue with watchers',
2016 2027 :description => 'This is the description',
2017 2028 :priority_id => 5,
2018 2029 :watcher_user_ids => ['2', '3']}
2019 2030 end
2020 2031 issue = Issue.find_by_subject('This is a new issue with watchers')
2021 2032 assert_not_nil issue
2022 2033 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
2023 2034
2024 2035 # Watchers added
2025 2036 assert_equal [2, 3], issue.watcher_user_ids.sort
2026 2037 assert issue.watched_by?(User.find(3))
2027 2038 # Watchers notified
2028 2039 mail = ActionMailer::Base.deliveries.last
2029 2040 assert_not_nil mail
2030 2041 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
2031 2042 end
2032 2043
2033 2044 def test_post_create_subissue
2034 2045 @request.session[:user_id] = 2
2035 2046
2036 2047 assert_difference 'Issue.count' do
2037 2048 post :create, :project_id => 1,
2038 2049 :issue => {:tracker_id => 1,
2039 2050 :subject => 'This is a child issue',
2040 2051 :parent_issue_id => '2'}
2041 2052 assert_response 302
2042 2053 end
2043 2054 issue = Issue.order('id DESC').first
2044 2055 assert_equal Issue.find(2), issue.parent
2045 2056 end
2046 2057
2047 2058 def test_post_create_subissue_with_sharp_parent_id
2048 2059 @request.session[:user_id] = 2
2049 2060
2050 2061 assert_difference 'Issue.count' do
2051 2062 post :create, :project_id => 1,
2052 2063 :issue => {:tracker_id => 1,
2053 2064 :subject => 'This is a child issue',
2054 2065 :parent_issue_id => '#2'}
2055 2066 assert_response 302
2056 2067 end
2057 2068 issue = Issue.order('id DESC').first
2058 2069 assert_equal Issue.find(2), issue.parent
2059 2070 end
2060 2071
2061 2072 def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
2062 2073 @request.session[:user_id] = 2
2063 2074
2064 2075 assert_no_difference 'Issue.count' do
2065 2076 post :create, :project_id => 1,
2066 2077 :issue => {:tracker_id => 1,
2067 2078 :subject => 'This is a child issue',
2068 2079 :parent_issue_id => '4'}
2069 2080
2070 2081 assert_response :success
2071 2082 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
2072 2083 assert_error_tag :content => /Parent task is invalid/i
2073 2084 end
2074 2085 end
2075 2086
2076 2087 def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
2077 2088 @request.session[:user_id] = 2
2078 2089
2079 2090 assert_no_difference 'Issue.count' do
2080 2091 post :create, :project_id => 1,
2081 2092 :issue => {:tracker_id => 1,
2082 2093 :subject => 'This is a child issue',
2083 2094 :parent_issue_id => '01ABC'}
2084 2095
2085 2096 assert_response :success
2086 2097 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
2087 2098 assert_error_tag :content => /Parent task is invalid/i
2088 2099 end
2089 2100 end
2090 2101
2091 2102 def test_post_create_private
2092 2103 @request.session[:user_id] = 2
2093 2104
2094 2105 assert_difference 'Issue.count' do
2095 2106 post :create, :project_id => 1,
2096 2107 :issue => {:tracker_id => 1,
2097 2108 :subject => 'This is a private issue',
2098 2109 :is_private => '1'}
2099 2110 end
2100 2111 issue = Issue.order('id DESC').first
2101 2112 assert issue.is_private?
2102 2113 end
2103 2114
2104 2115 def test_post_create_private_with_set_own_issues_private_permission
2105 2116 role = Role.find(1)
2106 2117 role.remove_permission! :set_issues_private
2107 2118 role.add_permission! :set_own_issues_private
2108 2119
2109 2120 @request.session[:user_id] = 2
2110 2121
2111 2122 assert_difference 'Issue.count' do
2112 2123 post :create, :project_id => 1,
2113 2124 :issue => {:tracker_id => 1,
2114 2125 :subject => 'This is a private issue',
2115 2126 :is_private => '1'}
2116 2127 end
2117 2128 issue = Issue.order('id DESC').first
2118 2129 assert issue.is_private?
2119 2130 end
2120 2131
2121 2132 def test_post_create_should_send_a_notification
2122 2133 ActionMailer::Base.deliveries.clear
2123 2134 @request.session[:user_id] = 2
2124 2135 assert_difference 'Issue.count' do
2125 2136 post :create, :project_id => 1,
2126 2137 :issue => {:tracker_id => 3,
2127 2138 :subject => 'This is the test_new issue',
2128 2139 :description => 'This is the description',
2129 2140 :priority_id => 5,
2130 2141 :estimated_hours => '',
2131 2142 :custom_field_values => {'2' => 'Value for field 2'}}
2132 2143 end
2133 2144 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2134 2145
2135 2146 assert_equal 1, ActionMailer::Base.deliveries.size
2136 2147 end
2137 2148
2138 2149 def test_post_create_should_preserve_fields_values_on_validation_failure
2139 2150 @request.session[:user_id] = 2
2140 2151 post :create, :project_id => 1,
2141 2152 :issue => {:tracker_id => 1,
2142 2153 # empty subject
2143 2154 :subject => '',
2144 2155 :description => 'This is a description',
2145 2156 :priority_id => 6,
2146 2157 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
2147 2158 assert_response :success
2148 2159 assert_template 'new'
2149 2160
2150 2161 assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
2151 2162 assert_select 'select[name=?]', 'issue[priority_id]' do
2152 2163 assert_select 'option[value=6][selected=selected]', :text => 'High'
2153 2164 end
2154 2165 # Custom fields
2155 2166 assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
2156 2167 assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
2157 2168 end
2158 2169 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
2159 2170 end
2160 2171
2161 2172 def test_post_create_with_failure_should_preserve_watchers
2162 2173 assert !User.find(8).member_of?(Project.find(1))
2163 2174
2164 2175 @request.session[:user_id] = 2
2165 2176 post :create, :project_id => 1,
2166 2177 :issue => {:tracker_id => 1,
2167 2178 :watcher_user_ids => ['3', '8']}
2168 2179 assert_response :success
2169 2180 assert_template 'new'
2170 2181
2171 2182 assert_select 'input[name=?][value=2]:not(checked)', 'issue[watcher_user_ids][]'
2172 2183 assert_select 'input[name=?][value=3][checked=checked]', 'issue[watcher_user_ids][]'
2173 2184 assert_select 'input[name=?][value=8][checked=checked]', 'issue[watcher_user_ids][]'
2174 2185 end
2175 2186
2176 2187 def test_post_create_should_ignore_non_safe_attributes
2177 2188 @request.session[:user_id] = 2
2178 2189 assert_nothing_raised do
2179 2190 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
2180 2191 end
2181 2192 end
2182 2193
2183 2194 def test_post_create_with_attachment
2184 2195 set_tmp_attachments_directory
2185 2196 @request.session[:user_id] = 2
2186 2197
2187 2198 assert_difference 'Issue.count' do
2188 2199 assert_difference 'Attachment.count' do
2189 2200 post :create, :project_id => 1,
2190 2201 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2191 2202 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2192 2203 end
2193 2204 end
2194 2205
2195 2206 issue = Issue.order('id DESC').first
2196 2207 attachment = Attachment.order('id DESC').first
2197 2208
2198 2209 assert_equal issue, attachment.container
2199 2210 assert_equal 2, attachment.author_id
2200 2211 assert_equal 'testfile.txt', attachment.filename
2201 2212 assert_equal 'text/plain', attachment.content_type
2202 2213 assert_equal 'test file', attachment.description
2203 2214 assert_equal 59, attachment.filesize
2204 2215 assert File.exists?(attachment.diskfile)
2205 2216 assert_equal 59, File.size(attachment.diskfile)
2206 2217 end
2207 2218
2208 2219 def test_post_create_with_attachment_should_notify_with_attachments
2209 2220 ActionMailer::Base.deliveries.clear
2210 2221 set_tmp_attachments_directory
2211 2222 @request.session[:user_id] = 2
2212 2223
2213 2224 with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
2214 2225 assert_difference 'Issue.count' do
2215 2226 post :create, :project_id => 1,
2216 2227 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2217 2228 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2218 2229 end
2219 2230 end
2220 2231
2221 2232 assert_not_nil ActionMailer::Base.deliveries.last
2222 2233 assert_select_email do
2223 2234 assert_select 'a[href^=?]', 'http://mydomain.foo/attachments/download', 'testfile.txt'
2224 2235 end
2225 2236 end
2226 2237
2227 2238 def test_post_create_with_failure_should_save_attachments
2228 2239 set_tmp_attachments_directory
2229 2240 @request.session[:user_id] = 2
2230 2241
2231 2242 assert_no_difference 'Issue.count' do
2232 2243 assert_difference 'Attachment.count' do
2233 2244 post :create, :project_id => 1,
2234 2245 :issue => { :tracker_id => '1', :subject => '' },
2235 2246 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2236 2247 assert_response :success
2237 2248 assert_template 'new'
2238 2249 end
2239 2250 end
2240 2251
2241 2252 attachment = Attachment.order('id DESC').first
2242 2253 assert_equal 'testfile.txt', attachment.filename
2243 2254 assert File.exists?(attachment.diskfile)
2244 2255 assert_nil attachment.container
2245 2256
2246 2257 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2247 2258 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2248 2259 end
2249 2260
2250 2261 def test_post_create_with_failure_should_keep_saved_attachments
2251 2262 set_tmp_attachments_directory
2252 2263 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2253 2264 @request.session[:user_id] = 2
2254 2265
2255 2266 assert_no_difference 'Issue.count' do
2256 2267 assert_no_difference 'Attachment.count' do
2257 2268 post :create, :project_id => 1,
2258 2269 :issue => { :tracker_id => '1', :subject => '' },
2259 2270 :attachments => {'p0' => {'token' => attachment.token}}
2260 2271 assert_response :success
2261 2272 assert_template 'new'
2262 2273 end
2263 2274 end
2264 2275
2265 2276 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2266 2277 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2267 2278 end
2268 2279
2269 2280 def test_post_create_should_attach_saved_attachments
2270 2281 set_tmp_attachments_directory
2271 2282 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2272 2283 @request.session[:user_id] = 2
2273 2284
2274 2285 assert_difference 'Issue.count' do
2275 2286 assert_no_difference 'Attachment.count' do
2276 2287 post :create, :project_id => 1,
2277 2288 :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
2278 2289 :attachments => {'p0' => {'token' => attachment.token}}
2279 2290 assert_response 302
2280 2291 end
2281 2292 end
2282 2293
2283 2294 issue = Issue.order('id DESC').first
2284 2295 assert_equal 1, issue.attachments.count
2285 2296
2286 2297 attachment.reload
2287 2298 assert_equal issue, attachment.container
2288 2299 end
2289 2300
2290 2301 def setup_without_workflow_privilege
2291 2302 WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
2292 2303 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2293 2304 end
2294 2305 private :setup_without_workflow_privilege
2295 2306
2296 2307 test "without workflow privilege #new should propose default status only" do
2297 2308 setup_without_workflow_privilege
2298 2309 get :new, :project_id => 1
2299 2310 assert_response :success
2300 2311 assert_template 'new'
2301 2312 assert_select 'select[name=?]', 'issue[status_id]' do
2302 2313 assert_select 'option', 1
2303 2314 assert_select 'option[value=?]', IssueStatus.default.id.to_s
2304 2315 end
2305 2316 end
2306 2317
2307 2318 test "without workflow privilege #new should accept default status" do
2308 2319 setup_without_workflow_privilege
2309 2320 assert_difference 'Issue.count' do
2310 2321 post :create, :project_id => 1,
2311 2322 :issue => {:tracker_id => 1,
2312 2323 :subject => 'This is an issue',
2313 2324 :status_id => 1}
2314 2325 end
2315 2326 issue = Issue.order('id').last
2316 2327 assert_equal IssueStatus.default, issue.status
2317 2328 end
2318 2329
2319 2330 test "without workflow privilege #new should ignore unauthorized status" do
2320 2331 setup_without_workflow_privilege
2321 2332 assert_difference 'Issue.count' do
2322 2333 post :create, :project_id => 1,
2323 2334 :issue => {:tracker_id => 1,
2324 2335 :subject => 'This is an issue',
2325 2336 :status_id => 3}
2326 2337 end
2327 2338 issue = Issue.order('id').last
2328 2339 assert_equal IssueStatus.default, issue.status
2329 2340 end
2330 2341
2331 2342 test "without workflow privilege #update should ignore status change" do
2332 2343 setup_without_workflow_privilege
2333 2344 assert_difference 'Journal.count' do
2334 2345 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2335 2346 end
2336 2347 assert_equal 1, Issue.find(1).status_id
2337 2348 end
2338 2349
2339 2350 test "without workflow privilege #update ignore attributes changes" do
2340 2351 setup_without_workflow_privilege
2341 2352 assert_difference 'Journal.count' do
2342 2353 put :update, :id => 1,
2343 2354 :issue => {:subject => 'changed', :assigned_to_id => 2,
2344 2355 :notes => 'just trying'}
2345 2356 end
2346 2357 issue = Issue.find(1)
2347 2358 assert_equal "Can't print recipes", issue.subject
2348 2359 assert_nil issue.assigned_to
2349 2360 end
2350 2361
2351 2362 def setup_with_workflow_privilege
2352 2363 WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
2353 2364 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2354 2365 :old_status_id => 1, :new_status_id => 3)
2355 2366 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2356 2367 :old_status_id => 1, :new_status_id => 4)
2357 2368 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2358 2369 end
2359 2370 private :setup_with_workflow_privilege
2360 2371
2361 2372 test "with workflow privilege #update should accept authorized status" do
2362 2373 setup_with_workflow_privilege
2363 2374 assert_difference 'Journal.count' do
2364 2375 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2365 2376 end
2366 2377 assert_equal 3, Issue.find(1).status_id
2367 2378 end
2368 2379
2369 2380 test "with workflow privilege #update should ignore unauthorized status" do
2370 2381 setup_with_workflow_privilege
2371 2382 assert_difference 'Journal.count' do
2372 2383 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2373 2384 end
2374 2385 assert_equal 1, Issue.find(1).status_id
2375 2386 end
2376 2387
2377 2388 test "with workflow privilege #update should accept authorized attributes changes" do
2378 2389 setup_with_workflow_privilege
2379 2390 assert_difference 'Journal.count' do
2380 2391 put :update, :id => 1, :issue => {:assigned_to_id => 2, :notes => 'just trying'}
2381 2392 end
2382 2393 issue = Issue.find(1)
2383 2394 assert_equal 2, issue.assigned_to_id
2384 2395 end
2385 2396
2386 2397 test "with workflow privilege #update should ignore unauthorized attributes changes" do
2387 2398 setup_with_workflow_privilege
2388 2399 assert_difference 'Journal.count' do
2389 2400 put :update, :id => 1, :issue => {:subject => 'changed', :notes => 'just trying'}
2390 2401 end
2391 2402 issue = Issue.find(1)
2392 2403 assert_equal "Can't print recipes", issue.subject
2393 2404 end
2394 2405
2395 2406 def setup_with_workflow_privilege_and_edit_issues_permission
2396 2407 setup_with_workflow_privilege
2397 2408 Role.anonymous.add_permission! :add_issues, :edit_issues
2398 2409 end
2399 2410 private :setup_with_workflow_privilege_and_edit_issues_permission
2400 2411
2401 2412 test "with workflow privilege and :edit_issues permission should accept authorized status" do
2402 2413 setup_with_workflow_privilege_and_edit_issues_permission
2403 2414 assert_difference 'Journal.count' do
2404 2415 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2405 2416 end
2406 2417 assert_equal 3, Issue.find(1).status_id
2407 2418 end
2408 2419
2409 2420 test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
2410 2421 setup_with_workflow_privilege_and_edit_issues_permission
2411 2422 assert_difference 'Journal.count' do
2412 2423 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2413 2424 end
2414 2425 assert_equal 1, Issue.find(1).status_id
2415 2426 end
2416 2427
2417 2428 test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
2418 2429 setup_with_workflow_privilege_and_edit_issues_permission
2419 2430 assert_difference 'Journal.count' do
2420 2431 put :update, :id => 1,
2421 2432 :issue => {:subject => 'changed', :assigned_to_id => 2,
2422 2433 :notes => 'just trying'}
2423 2434 end
2424 2435 issue = Issue.find(1)
2425 2436 assert_equal "changed", issue.subject
2426 2437 assert_equal 2, issue.assigned_to_id
2427 2438 end
2428 2439
2429 2440 def test_new_as_copy
2430 2441 @request.session[:user_id] = 2
2431 2442 get :new, :project_id => 1, :copy_from => 1
2432 2443
2433 2444 assert_response :success
2434 2445 assert_template 'new'
2435 2446
2436 2447 assert_not_nil assigns(:issue)
2437 2448 orig = Issue.find(1)
2438 2449 assert_equal 1, assigns(:issue).project_id
2439 2450 assert_equal orig.subject, assigns(:issue).subject
2440 2451 assert assigns(:issue).copy?
2441 2452
2442 2453 assert_select 'form[id=issue-form][action=/projects/ecookbook/issues]' do
2443 2454 assert_select 'select[name=?]', 'issue[project_id]' do
2444 2455 assert_select 'option[value=1][selected=selected]', :text => 'eCookbook'
2445 2456 assert_select 'option[value=2]:not([selected])', :text => 'OnlineStore'
2446 2457 end
2447 2458 assert_select 'input[name=copy_from][value=1]'
2448 2459 end
2449 2460
2450 2461 # "New issue" menu item should not link to copy
2451 2462 assert_select '#main-menu a.new-issue[href=/projects/ecookbook/issues/new]'
2452 2463 end
2453 2464
2454 2465 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
2455 2466 @request.session[:user_id] = 2
2456 2467 issue = Issue.find(3)
2457 2468 assert issue.attachments.count > 0
2458 2469 get :new, :project_id => 1, :copy_from => 3
2459 2470
2460 2471 assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value=1]'
2461 2472 end
2462 2473
2463 2474 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
2464 2475 @request.session[:user_id] = 2
2465 2476 issue = Issue.find(3)
2466 2477 issue.attachments.delete_all
2467 2478 get :new, :project_id => 1, :copy_from => 3
2468 2479
2469 2480 assert_select 'input[name=copy_attachments]', 0
2470 2481 end
2471 2482
2472 2483 def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
2473 2484 @request.session[:user_id] = 2
2474 2485 issue = Issue.generate_with_descendants!
2475 2486 get :new, :project_id => 1, :copy_from => issue.id
2476 2487
2477 2488 assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value=1]'
2478 2489 end
2479 2490
2480 2491 def test_new_as_copy_with_invalid_issue_should_respond_with_404
2481 2492 @request.session[:user_id] = 2
2482 2493 get :new, :project_id => 1, :copy_from => 99999
2483 2494 assert_response 404
2484 2495 end
2485 2496
2486 2497 def test_create_as_copy_on_different_project
2487 2498 @request.session[:user_id] = 2
2488 2499 assert_difference 'Issue.count' do
2489 2500 post :create, :project_id => 1, :copy_from => 1,
2490 2501 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2491 2502
2492 2503 assert_not_nil assigns(:issue)
2493 2504 assert assigns(:issue).copy?
2494 2505 end
2495 2506 issue = Issue.order('id DESC').first
2496 2507 assert_redirected_to "/issues/#{issue.id}"
2497 2508
2498 2509 assert_equal 2, issue.project_id
2499 2510 assert_equal 3, issue.tracker_id
2500 2511 assert_equal 'Copy', issue.subject
2501 2512 end
2502 2513
2503 2514 def test_create_as_copy_should_copy_attachments
2504 2515 @request.session[:user_id] = 2
2505 2516 issue = Issue.find(3)
2506 2517 count = issue.attachments.count
2507 2518 assert count > 0
2508 2519 assert_difference 'Issue.count' do
2509 2520 assert_difference 'Attachment.count', count do
2510 2521 assert_difference 'Journal.count', 2 do
2511 2522 post :create, :project_id => 1, :copy_from => 3,
2512 2523 :issue => {:project_id => '1', :tracker_id => '3',
2513 2524 :status_id => '1', :subject => 'Copy with attachments'},
2514 2525 :copy_attachments => '1'
2515 2526 end
2516 2527 end
2517 2528 end
2518 2529 copy = Issue.order('id DESC').first
2519 2530 assert_equal count, copy.attachments.count
2520 2531 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
2521 2532 end
2522 2533
2523 2534 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
2524 2535 @request.session[:user_id] = 2
2525 2536 issue = Issue.find(3)
2526 2537 count = issue.attachments.count
2527 2538 assert count > 0
2528 2539 assert_difference 'Issue.count' do
2529 2540 assert_no_difference 'Attachment.count' do
2530 2541 assert_difference 'Journal.count', 2 do
2531 2542 post :create, :project_id => 1, :copy_from => 3,
2532 2543 :issue => {:project_id => '1', :tracker_id => '3',
2533 2544 :status_id => '1', :subject => 'Copy with attachments'}
2534 2545 end
2535 2546 end
2536 2547 end
2537 2548 copy = Issue.order('id DESC').first
2538 2549 assert_equal 0, copy.attachments.count
2539 2550 end
2540 2551
2541 2552 def test_create_as_copy_with_attachments_should_add_new_files
2542 2553 @request.session[:user_id] = 2
2543 2554 issue = Issue.find(3)
2544 2555 count = issue.attachments.count
2545 2556 assert count > 0
2546 2557 assert_difference 'Issue.count' do
2547 2558 assert_difference 'Attachment.count', count + 1 do
2548 2559 assert_difference 'Journal.count', 2 do
2549 2560 post :create, :project_id => 1, :copy_from => 3,
2550 2561 :issue => {:project_id => '1', :tracker_id => '3',
2551 2562 :status_id => '1', :subject => 'Copy with attachments'},
2552 2563 :copy_attachments => '1',
2553 2564 :attachments => {'1' =>
2554 2565 {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
2555 2566 'description' => 'test file'}}
2556 2567 end
2557 2568 end
2558 2569 end
2559 2570 copy = Issue.order('id DESC').first
2560 2571 assert_equal count + 1, copy.attachments.count
2561 2572 end
2562 2573
2563 2574 def test_create_as_copy_should_add_relation_with_copied_issue
2564 2575 @request.session[:user_id] = 2
2565 2576 assert_difference 'Issue.count' do
2566 2577 assert_difference 'IssueRelation.count' do
2567 2578 post :create, :project_id => 1, :copy_from => 1,
2568 2579 :issue => {:project_id => '1', :tracker_id => '3',
2569 2580 :status_id => '1', :subject => 'Copy'}
2570 2581 end
2571 2582 end
2572 2583 copy = Issue.order('id DESC').first
2573 2584 assert_equal 1, copy.relations.size
2574 2585 end
2575 2586
2576 2587 def test_create_as_copy_should_copy_subtasks
2577 2588 @request.session[:user_id] = 2
2578 2589 issue = Issue.generate_with_descendants!
2579 2590 count = issue.descendants.count
2580 2591 assert_difference 'Issue.count', count + 1 do
2581 2592 assert_difference 'Journal.count', (count + 1) * 2 do
2582 2593 post :create, :project_id => 1, :copy_from => issue.id,
2583 2594 :issue => {:project_id => '1', :tracker_id => '3',
2584 2595 :status_id => '1', :subject => 'Copy with subtasks'},
2585 2596 :copy_subtasks => '1'
2586 2597 end
2587 2598 end
2588 2599 copy = Issue.where(:parent_id => nil).order('id DESC').first
2589 2600 assert_equal count, copy.descendants.count
2590 2601 assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
2591 2602 end
2592 2603
2593 2604 def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
2594 2605 @request.session[:user_id] = 2
2595 2606 issue = Issue.generate_with_descendants!
2596 2607 assert_difference 'Issue.count', 1 do
2597 2608 assert_difference 'Journal.count', 2 do
2598 2609 post :create, :project_id => 1, :copy_from => 3,
2599 2610 :issue => {:project_id => '1', :tracker_id => '3',
2600 2611 :status_id => '1', :subject => 'Copy with subtasks'}
2601 2612 end
2602 2613 end
2603 2614 copy = Issue.where(:parent_id => nil).order('id DESC').first
2604 2615 assert_equal 0, copy.descendants.count
2605 2616 end
2606 2617
2607 2618 def test_create_as_copy_with_failure
2608 2619 @request.session[:user_id] = 2
2609 2620 post :create, :project_id => 1, :copy_from => 1,
2610 2621 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
2611 2622
2612 2623 assert_response :success
2613 2624 assert_template 'new'
2614 2625
2615 2626 assert_not_nil assigns(:issue)
2616 2627 assert assigns(:issue).copy?
2617 2628
2618 2629 assert_select 'form#issue-form[action=/projects/ecookbook/issues]' do
2619 2630 assert_select 'select[name=?]', 'issue[project_id]' do
2620 2631 assert_select 'option[value=1]:not([selected])', :text => 'eCookbook'
2621 2632 assert_select 'option[value=2][selected=selected]', :text => 'OnlineStore'
2622 2633 end
2623 2634 assert_select 'input[name=copy_from][value=1]'
2624 2635 end
2625 2636 end
2626 2637
2627 2638 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
2628 2639 @request.session[:user_id] = 2
2629 2640 assert !User.find(2).member_of?(Project.find(4))
2630 2641
2631 2642 assert_difference 'Issue.count' do
2632 2643 post :create, :project_id => 1, :copy_from => 1,
2633 2644 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2634 2645 end
2635 2646 issue = Issue.order('id DESC').first
2636 2647 assert_equal 1, issue.project_id
2637 2648 end
2638 2649
2639 2650 def test_get_edit
2640 2651 @request.session[:user_id] = 2
2641 2652 get :edit, :id => 1
2642 2653 assert_response :success
2643 2654 assert_template 'edit'
2644 2655 assert_not_nil assigns(:issue)
2645 2656 assert_equal Issue.find(1), assigns(:issue)
2646 2657
2647 2658 # Be sure we don't display inactive IssuePriorities
2648 2659 assert ! IssuePriority.find(15).active?
2649 2660 assert_select 'select[name=?]', 'issue[priority_id]' do
2650 2661 assert_select 'option[value=15]', 0
2651 2662 end
2652 2663 end
2653 2664
2654 2665 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
2655 2666 @request.session[:user_id] = 2
2656 2667 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
2657 2668
2658 2669 get :edit, :id => 1
2659 2670 assert_select 'input[name=?]', 'time_entry[hours]'
2660 2671 end
2661 2672
2662 2673 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
2663 2674 @request.session[:user_id] = 2
2664 2675 Role.find_by_name('Manager').remove_permission! :log_time
2665 2676
2666 2677 get :edit, :id => 1
2667 2678 assert_select 'input[name=?]', 'time_entry[hours]', 0
2668 2679 end
2669 2680
2670 2681 def test_get_edit_with_params
2671 2682 @request.session[:user_id] = 2
2672 2683 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
2673 2684 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
2674 2685 assert_response :success
2675 2686 assert_template 'edit'
2676 2687
2677 2688 issue = assigns(:issue)
2678 2689 assert_not_nil issue
2679 2690
2680 2691 assert_equal 5, issue.status_id
2681 2692 assert_select 'select[name=?]', 'issue[status_id]' do
2682 2693 assert_select 'option[value=5][selected=selected]', :text => 'Closed'
2683 2694 end
2684 2695
2685 2696 assert_equal 7, issue.priority_id
2686 2697 assert_select 'select[name=?]', 'issue[priority_id]' do
2687 2698 assert_select 'option[value=7][selected=selected]', :text => 'Urgent'
2688 2699 end
2689 2700
2690 2701 assert_select 'input[name=?][value=2.5]', 'time_entry[hours]'
2691 2702 assert_select 'select[name=?]', 'time_entry[activity_id]' do
2692 2703 assert_select 'option[value=10][selected=selected]', :text => 'Development'
2693 2704 end
2694 2705 assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
2695 2706 end
2696 2707
2697 2708 def test_get_edit_with_multi_custom_field
2698 2709 field = CustomField.find(1)
2699 2710 field.update_attribute :multiple, true
2700 2711 issue = Issue.find(1)
2701 2712 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2702 2713 issue.save!
2703 2714
2704 2715 @request.session[:user_id] = 2
2705 2716 get :edit, :id => 1
2706 2717 assert_response :success
2707 2718 assert_template 'edit'
2708 2719
2709 2720 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
2710 2721 assert_select 'option', 3
2711 2722 assert_select 'option[value=MySQL][selected=selected]'
2712 2723 assert_select 'option[value=Oracle][selected=selected]'
2713 2724 assert_select 'option[value=PostgreSQL]:not([selected])'
2714 2725 end
2715 2726 end
2716 2727
2717 2728 def test_update_form_for_existing_issue
2718 2729 @request.session[:user_id] = 2
2719 2730 xhr :put, :update_form, :project_id => 1,
2720 2731 :id => 1,
2721 2732 :issue => {:tracker_id => 2,
2722 2733 :subject => 'This is the test_new issue',
2723 2734 :description => 'This is the description',
2724 2735 :priority_id => 5}
2725 2736 assert_response :success
2726 2737 assert_equal 'text/javascript', response.content_type
2727 2738 assert_template 'update_form'
2728 2739 assert_template :partial => '_form'
2729 2740
2730 2741 issue = assigns(:issue)
2731 2742 assert_kind_of Issue, issue
2732 2743 assert_equal 1, issue.id
2733 2744 assert_equal 1, issue.project_id
2734 2745 assert_equal 2, issue.tracker_id
2735 2746 assert_equal 'This is the test_new issue', issue.subject
2736 2747 end
2737 2748
2738 2749 def test_update_form_for_existing_issue_should_keep_issue_author
2739 2750 @request.session[:user_id] = 3
2740 2751 xhr :put, :update_form, :project_id => 1, :id => 1, :issue => {:subject => 'Changed'}
2741 2752 assert_response :success
2742 2753 assert_equal 'text/javascript', response.content_type
2743 2754
2744 2755 issue = assigns(:issue)
2745 2756 assert_equal User.find(2), issue.author
2746 2757 assert_equal 2, issue.author_id
2747 2758 assert_not_equal User.current, issue.author
2748 2759 end
2749 2760
2750 2761 def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
2751 2762 @request.session[:user_id] = 2
2752 2763 WorkflowTransition.delete_all
2753 2764 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
2754 2765 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
2755 2766 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
2756 2767
2757 2768 xhr :put, :update_form, :project_id => 1,
2758 2769 :id => 2,
2759 2770 :issue => {:tracker_id => 2,
2760 2771 :status_id => 5,
2761 2772 :subject => 'This is an issue'}
2762 2773
2763 2774 assert_equal 5, assigns(:issue).status_id
2764 2775 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
2765 2776 end
2766 2777
2767 2778 def test_update_form_for_existing_issue_with_project_change
2768 2779 @request.session[:user_id] = 2
2769 2780 xhr :put, :update_form, :project_id => 1,
2770 2781 :id => 1,
2771 2782 :issue => {:project_id => 2,
2772 2783 :tracker_id => 2,
2773 2784 :subject => 'This is the test_new issue',
2774 2785 :description => 'This is the description',
2775 2786 :priority_id => 5}
2776 2787 assert_response :success
2777 2788 assert_template :partial => '_form'
2778 2789
2779 2790 issue = assigns(:issue)
2780 2791 assert_kind_of Issue, issue
2781 2792 assert_equal 1, issue.id
2782 2793 assert_equal 2, issue.project_id
2783 2794 assert_equal 2, issue.tracker_id
2784 2795 assert_equal 'This is the test_new issue', issue.subject
2785 2796 end
2786 2797
2787 2798 def test_update_form_should_propose_default_status_for_existing_issue
2788 2799 @request.session[:user_id] = 2
2789 2800 WorkflowTransition.delete_all
2790 2801 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
2791 2802
2792 2803 xhr :put, :update_form, :project_id => 1, :id => 2
2793 2804 assert_response :success
2794 2805 assert_equal [2,3], assigns(:allowed_statuses).map(&:id).sort
2795 2806 end
2796 2807
2797 2808 def test_put_update_without_custom_fields_param
2798 2809 @request.session[:user_id] = 2
2799 2810 ActionMailer::Base.deliveries.clear
2800 2811
2801 2812 issue = Issue.find(1)
2802 2813 assert_equal '125', issue.custom_value_for(2).value
2803 2814 old_subject = issue.subject
2804 2815 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
2805 2816
2806 2817 assert_difference('Journal.count') do
2807 2818 assert_difference('JournalDetail.count', 2) do
2808 2819 put :update, :id => 1, :issue => {:subject => new_subject,
2809 2820 :priority_id => '6',
2810 2821 :category_id => '1' # no change
2811 2822 }
2812 2823 end
2813 2824 end
2814 2825 assert_redirected_to :action => 'show', :id => '1'
2815 2826 issue.reload
2816 2827 assert_equal new_subject, issue.subject
2817 2828 # Make sure custom fields were not cleared
2818 2829 assert_equal '125', issue.custom_value_for(2).value
2819 2830
2820 2831 mail = ActionMailer::Base.deliveries.last
2821 2832 assert_not_nil mail
2822 2833 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2823 2834 assert_mail_body_match "Subject changed from #{old_subject} to #{new_subject}", mail
2824 2835 end
2825 2836
2826 2837 def test_put_update_with_project_change
2827 2838 @request.session[:user_id] = 2
2828 2839 ActionMailer::Base.deliveries.clear
2829 2840
2830 2841 assert_difference('Journal.count') do
2831 2842 assert_difference('JournalDetail.count', 3) do
2832 2843 put :update, :id => 1, :issue => {:project_id => '2',
2833 2844 :tracker_id => '1', # no change
2834 2845 :priority_id => '6',
2835 2846 :category_id => '3'
2836 2847 }
2837 2848 end
2838 2849 end
2839 2850 assert_redirected_to :action => 'show', :id => '1'
2840 2851 issue = Issue.find(1)
2841 2852 assert_equal 2, issue.project_id
2842 2853 assert_equal 1, issue.tracker_id
2843 2854 assert_equal 6, issue.priority_id
2844 2855 assert_equal 3, issue.category_id
2845 2856
2846 2857 mail = ActionMailer::Base.deliveries.last
2847 2858 assert_not_nil mail
2848 2859 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2849 2860 assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
2850 2861 end
2851 2862
2852 2863 def test_put_update_with_tracker_change
2853 2864 @request.session[:user_id] = 2
2854 2865 ActionMailer::Base.deliveries.clear
2855 2866
2856 2867 assert_difference('Journal.count') do
2857 2868 assert_difference('JournalDetail.count', 2) do
2858 2869 put :update, :id => 1, :issue => {:project_id => '1',
2859 2870 :tracker_id => '2',
2860 2871 :priority_id => '6'
2861 2872 }
2862 2873 end
2863 2874 end
2864 2875 assert_redirected_to :action => 'show', :id => '1'
2865 2876 issue = Issue.find(1)
2866 2877 assert_equal 1, issue.project_id
2867 2878 assert_equal 2, issue.tracker_id
2868 2879 assert_equal 6, issue.priority_id
2869 2880 assert_equal 1, issue.category_id
2870 2881
2871 2882 mail = ActionMailer::Base.deliveries.last
2872 2883 assert_not_nil mail
2873 2884 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2874 2885 assert_mail_body_match "Tracker changed from Bug to Feature request", mail
2875 2886 end
2876 2887
2877 2888 def test_put_update_with_custom_field_change
2878 2889 @request.session[:user_id] = 2
2879 2890 issue = Issue.find(1)
2880 2891 assert_equal '125', issue.custom_value_for(2).value
2881 2892
2882 2893 assert_difference('Journal.count') do
2883 2894 assert_difference('JournalDetail.count', 3) do
2884 2895 put :update, :id => 1, :issue => {:subject => 'Custom field change',
2885 2896 :priority_id => '6',
2886 2897 :category_id => '1', # no change
2887 2898 :custom_field_values => { '2' => 'New custom value' }
2888 2899 }
2889 2900 end
2890 2901 end
2891 2902 assert_redirected_to :action => 'show', :id => '1'
2892 2903 issue.reload
2893 2904 assert_equal 'New custom value', issue.custom_value_for(2).value
2894 2905
2895 2906 mail = ActionMailer::Base.deliveries.last
2896 2907 assert_not_nil mail
2897 2908 assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
2898 2909 end
2899 2910
2900 2911 def test_put_update_with_multi_custom_field_change
2901 2912 field = CustomField.find(1)
2902 2913 field.update_attribute :multiple, true
2903 2914 issue = Issue.find(1)
2904 2915 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2905 2916 issue.save!
2906 2917
2907 2918 @request.session[:user_id] = 2
2908 2919 assert_difference('Journal.count') do
2909 2920 assert_difference('JournalDetail.count', 3) do
2910 2921 put :update, :id => 1,
2911 2922 :issue => {
2912 2923 :subject => 'Custom field change',
2913 2924 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
2914 2925 }
2915 2926 end
2916 2927 end
2917 2928 assert_redirected_to :action => 'show', :id => '1'
2918 2929 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
2919 2930 end
2920 2931
2921 2932 def test_put_update_with_status_and_assignee_change
2922 2933 issue = Issue.find(1)
2923 2934 assert_equal 1, issue.status_id
2924 2935 @request.session[:user_id] = 2
2925 2936 assert_difference('TimeEntry.count', 0) do
2926 2937 put :update,
2927 2938 :id => 1,
2928 2939 :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
2929 2940 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
2930 2941 end
2931 2942 assert_redirected_to :action => 'show', :id => '1'
2932 2943 issue.reload
2933 2944 assert_equal 2, issue.status_id
2934 2945 j = Journal.order('id DESC').first
2935 2946 assert_equal 'Assigned to dlopper', j.notes
2936 2947 assert_equal 2, j.details.size
2937 2948
2938 2949 mail = ActionMailer::Base.deliveries.last
2939 2950 assert_mail_body_match "Status changed from New to Assigned", mail
2940 2951 # subject should contain the new status
2941 2952 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
2942 2953 end
2943 2954
2944 2955 def test_put_update_with_note_only
2945 2956 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
2946 2957 # anonymous user
2947 2958 put :update,
2948 2959 :id => 1,
2949 2960 :issue => { :notes => notes }
2950 2961 assert_redirected_to :action => 'show', :id => '1'
2951 2962 j = Journal.order('id DESC').first
2952 2963 assert_equal notes, j.notes
2953 2964 assert_equal 0, j.details.size
2954 2965 assert_equal User.anonymous, j.user
2955 2966
2956 2967 mail = ActionMailer::Base.deliveries.last
2957 2968 assert_mail_body_match notes, mail
2958 2969 end
2959 2970
2960 2971 def test_put_update_with_private_note_only
2961 2972 notes = 'Private note'
2962 2973 @request.session[:user_id] = 2
2963 2974
2964 2975 assert_difference 'Journal.count' do
2965 2976 put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
2966 2977 assert_redirected_to :action => 'show', :id => '1'
2967 2978 end
2968 2979
2969 2980 j = Journal.order('id DESC').first
2970 2981 assert_equal notes, j.notes
2971 2982 assert_equal true, j.private_notes
2972 2983 end
2973 2984
2974 2985 def test_put_update_with_private_note_and_changes
2975 2986 notes = 'Private note'
2976 2987 @request.session[:user_id] = 2
2977 2988
2978 2989 assert_difference 'Journal.count', 2 do
2979 2990 put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
2980 2991 assert_redirected_to :action => 'show', :id => '1'
2981 2992 end
2982 2993
2983 2994 j = Journal.order('id DESC').first
2984 2995 assert_equal notes, j.notes
2985 2996 assert_equal true, j.private_notes
2986 2997 assert_equal 0, j.details.count
2987 2998
2988 2999 j = Journal.order('id DESC').offset(1).first
2989 3000 assert_nil j.notes
2990 3001 assert_equal false, j.private_notes
2991 3002 assert_equal 1, j.details.count
2992 3003 end
2993 3004
2994 3005 def test_put_update_with_note_and_spent_time
2995 3006 @request.session[:user_id] = 2
2996 3007 spent_hours_before = Issue.find(1).spent_hours
2997 3008 assert_difference('TimeEntry.count') do
2998 3009 put :update,
2999 3010 :id => 1,
3000 3011 :issue => { :notes => '2.5 hours added' },
3001 3012 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
3002 3013 end
3003 3014 assert_redirected_to :action => 'show', :id => '1'
3004 3015
3005 3016 issue = Issue.find(1)
3006 3017
3007 3018 j = Journal.order('id DESC').first
3008 3019 assert_equal '2.5 hours added', j.notes
3009 3020 assert_equal 0, j.details.size
3010 3021
3011 3022 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
3012 3023 assert_not_nil t
3013 3024 assert_equal 2.5, t.hours
3014 3025 assert_equal spent_hours_before + 2.5, issue.spent_hours
3015 3026 end
3016 3027
3017 3028 def test_put_update_should_preserve_parent_issue_even_if_not_visible
3018 3029 parent = Issue.generate!(:project_id => 1, :is_private => true)
3019 3030 issue = Issue.generate!(:parent_issue_id => parent.id)
3020 3031 assert !parent.visible?(User.find(3))
3021 3032 @request.session[:user_id] = 3
3022 3033
3023 3034 get :edit, :id => issue.id
3024 3035 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
3025 3036
3026 3037 put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
3027 3038 assert_response 302
3028 3039 assert_equal parent, issue.parent
3029 3040 end
3030 3041
3031 3042 def test_put_update_with_attachment_only
3032 3043 set_tmp_attachments_directory
3033 3044
3034 3045 # Delete all fixtured journals, a race condition can occur causing the wrong
3035 3046 # journal to get fetched in the next find.
3036 3047 Journal.delete_all
3037 3048
3038 3049 # anonymous user
3039 3050 assert_difference 'Attachment.count' do
3040 3051 put :update, :id => 1,
3041 3052 :issue => {:notes => ''},
3042 3053 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3043 3054 end
3044 3055
3045 3056 assert_redirected_to :action => 'show', :id => '1'
3046 3057 j = Issue.find(1).journals.reorder('id DESC').first
3047 3058 assert j.notes.blank?
3048 3059 assert_equal 1, j.details.size
3049 3060 assert_equal 'testfile.txt', j.details.first.value
3050 3061 assert_equal User.anonymous, j.user
3051 3062
3052 3063 attachment = Attachment.order('id DESC').first
3053 3064 assert_equal Issue.find(1), attachment.container
3054 3065 assert_equal User.anonymous, attachment.author
3055 3066 assert_equal 'testfile.txt', attachment.filename
3056 3067 assert_equal 'text/plain', attachment.content_type
3057 3068 assert_equal 'test file', attachment.description
3058 3069 assert_equal 59, attachment.filesize
3059 3070 assert File.exists?(attachment.diskfile)
3060 3071 assert_equal 59, File.size(attachment.diskfile)
3061 3072
3062 3073 mail = ActionMailer::Base.deliveries.last
3063 3074 assert_mail_body_match 'testfile.txt', mail
3064 3075 end
3065 3076
3066 3077 def test_put_update_with_failure_should_save_attachments
3067 3078 set_tmp_attachments_directory
3068 3079 @request.session[:user_id] = 2
3069 3080
3070 3081 assert_no_difference 'Journal.count' do
3071 3082 assert_difference 'Attachment.count' do
3072 3083 put :update, :id => 1,
3073 3084 :issue => { :subject => '' },
3074 3085 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3075 3086 assert_response :success
3076 3087 assert_template 'edit'
3077 3088 end
3078 3089 end
3079 3090
3080 3091 attachment = Attachment.order('id DESC').first
3081 3092 assert_equal 'testfile.txt', attachment.filename
3082 3093 assert File.exists?(attachment.diskfile)
3083 3094 assert_nil attachment.container
3084 3095
3085 3096 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3086 3097 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3087 3098 end
3088 3099
3089 3100 def test_put_update_with_failure_should_keep_saved_attachments
3090 3101 set_tmp_attachments_directory
3091 3102 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3092 3103 @request.session[:user_id] = 2
3093 3104
3094 3105 assert_no_difference 'Journal.count' do
3095 3106 assert_no_difference 'Attachment.count' do
3096 3107 put :update, :id => 1,
3097 3108 :issue => { :subject => '' },
3098 3109 :attachments => {'p0' => {'token' => attachment.token}}
3099 3110 assert_response :success
3100 3111 assert_template 'edit'
3101 3112 end
3102 3113 end
3103 3114
3104 3115 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3105 3116 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3106 3117 end
3107 3118
3108 3119 def test_put_update_should_attach_saved_attachments
3109 3120 set_tmp_attachments_directory
3110 3121 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3111 3122 @request.session[:user_id] = 2
3112 3123
3113 3124 assert_difference 'Journal.count' do
3114 3125 assert_difference 'JournalDetail.count' do
3115 3126 assert_no_difference 'Attachment.count' do
3116 3127 put :update, :id => 1,
3117 3128 :issue => {:notes => 'Attachment added'},
3118 3129 :attachments => {'p0' => {'token' => attachment.token}}
3119 3130 assert_redirected_to '/issues/1'
3120 3131 end
3121 3132 end
3122 3133 end
3123 3134
3124 3135 attachment.reload
3125 3136 assert_equal Issue.find(1), attachment.container
3126 3137
3127 3138 journal = Journal.order('id DESC').first
3128 3139 assert_equal 1, journal.details.size
3129 3140 assert_equal 'testfile.txt', journal.details.first.value
3130 3141 end
3131 3142
3132 3143 def test_put_update_with_attachment_that_fails_to_save
3133 3144 set_tmp_attachments_directory
3134 3145
3135 3146 # Delete all fixtured journals, a race condition can occur causing the wrong
3136 3147 # journal to get fetched in the next find.
3137 3148 Journal.delete_all
3138 3149
3139 3150 # Mock out the unsaved attachment
3140 3151 Attachment.any_instance.stubs(:create).returns(Attachment.new)
3141 3152
3142 3153 # anonymous user
3143 3154 put :update,
3144 3155 :id => 1,
3145 3156 :issue => {:notes => ''},
3146 3157 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
3147 3158 assert_redirected_to :action => 'show', :id => '1'
3148 3159 assert_equal '1 file(s) could not be saved.', flash[:warning]
3149 3160 end
3150 3161
3151 3162 def test_put_update_with_no_change
3152 3163 issue = Issue.find(1)
3153 3164 issue.journals.clear
3154 3165 ActionMailer::Base.deliveries.clear
3155 3166
3156 3167 put :update,
3157 3168 :id => 1,
3158 3169 :issue => {:notes => ''}
3159 3170 assert_redirected_to :action => 'show', :id => '1'
3160 3171
3161 3172 issue.reload
3162 3173 assert issue.journals.empty?
3163 3174 # No email should be sent
3164 3175 assert ActionMailer::Base.deliveries.empty?
3165 3176 end
3166 3177
3167 3178 def test_put_update_should_send_a_notification
3168 3179 @request.session[:user_id] = 2
3169 3180 ActionMailer::Base.deliveries.clear
3170 3181 issue = Issue.find(1)
3171 3182 old_subject = issue.subject
3172 3183 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
3173 3184
3174 3185 put :update, :id => 1, :issue => {:subject => new_subject,
3175 3186 :priority_id => '6',
3176 3187 :category_id => '1' # no change
3177 3188 }
3178 3189 assert_equal 1, ActionMailer::Base.deliveries.size
3179 3190 end
3180 3191
3181 3192 def test_put_update_with_invalid_spent_time_hours_only
3182 3193 @request.session[:user_id] = 2
3183 3194 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3184 3195
3185 3196 assert_no_difference('Journal.count') do
3186 3197 put :update,
3187 3198 :id => 1,
3188 3199 :issue => {:notes => notes},
3189 3200 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
3190 3201 end
3191 3202 assert_response :success
3192 3203 assert_template 'edit'
3193 3204
3194 3205 assert_error_tag :descendant => {:content => /Activity #{ESCAPED_CANT} be blank/}
3195 3206 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3196 3207 assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
3197 3208 end
3198 3209
3199 3210 def test_put_update_with_invalid_spent_time_comments_only
3200 3211 @request.session[:user_id] = 2
3201 3212 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3202 3213
3203 3214 assert_no_difference('Journal.count') do
3204 3215 put :update,
3205 3216 :id => 1,
3206 3217 :issue => {:notes => notes},
3207 3218 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
3208 3219 end
3209 3220 assert_response :success
3210 3221 assert_template 'edit'
3211 3222
3212 3223 assert_error_tag :descendant => {:content => /Activity #{ESCAPED_CANT} be blank/}
3213 3224 assert_error_tag :descendant => {:content => /Hours #{ESCAPED_CANT} be blank/}
3214 3225 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3215 3226 assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
3216 3227 end
3217 3228
3218 3229 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
3219 3230 issue = Issue.find(2)
3220 3231 @request.session[:user_id] = 2
3221 3232
3222 3233 put :update,
3223 3234 :id => issue.id,
3224 3235 :issue => {
3225 3236 :fixed_version_id => 4
3226 3237 }
3227 3238
3228 3239 assert_response :redirect
3229 3240 issue.reload
3230 3241 assert_equal 4, issue.fixed_version_id
3231 3242 assert_not_equal issue.project_id, issue.fixed_version.project_id
3232 3243 end
3233 3244
3234 3245 def test_put_update_should_redirect_back_using_the_back_url_parameter
3235 3246 issue = Issue.find(2)
3236 3247 @request.session[:user_id] = 2
3237 3248
3238 3249 put :update,
3239 3250 :id => issue.id,
3240 3251 :issue => {
3241 3252 :fixed_version_id => 4
3242 3253 },
3243 3254 :back_url => '/issues'
3244 3255
3245 3256 assert_response :redirect
3246 3257 assert_redirected_to '/issues'
3247 3258 end
3248 3259
3249 3260 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3250 3261 issue = Issue.find(2)
3251 3262 @request.session[:user_id] = 2
3252 3263
3253 3264 put :update,
3254 3265 :id => issue.id,
3255 3266 :issue => {
3256 3267 :fixed_version_id => 4
3257 3268 },
3258 3269 :back_url => 'http://google.com'
3259 3270
3260 3271 assert_response :redirect
3261 3272 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3262 3273 end
3263 3274
3264 3275 def test_get_bulk_edit
3265 3276 @request.session[:user_id] = 2
3266 3277 get :bulk_edit, :ids => [1, 2]
3267 3278 assert_response :success
3268 3279 assert_template 'bulk_edit'
3269 3280
3270 3281 assert_select 'ul#bulk-selection' do
3271 3282 assert_select 'li', 2
3272 3283 assert_select 'li a', :text => 'Bug #1'
3273 3284 end
3274 3285
3275 3286 assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
3276 3287 assert_select 'input[name=?]', 'ids[]', 2
3277 3288 assert_select 'input[name=?][value=1][type=hidden]', 'ids[]'
3278 3289
3279 3290 assert_select 'select[name=?]', 'issue[project_id]'
3280 3291 assert_select 'input[name=?]', 'issue[parent_issue_id]'
3281 3292
3282 3293 # Project specific custom field, date type
3283 3294 field = CustomField.find(9)
3284 3295 assert !field.is_for_all?
3285 3296 assert_equal 'date', field.field_format
3286 3297 assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3287 3298
3288 3299 # System wide custom field
3289 3300 assert CustomField.find(1).is_for_all?
3290 3301 assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3291 3302
3292 3303 # Be sure we don't display inactive IssuePriorities
3293 3304 assert ! IssuePriority.find(15).active?
3294 3305 assert_select 'select[name=?]', 'issue[priority_id]' do
3295 3306 assert_select 'option[value=15]', 0
3296 3307 end
3297 3308 end
3298 3309 end
3299 3310
3300 3311 def test_get_bulk_edit_on_different_projects
3301 3312 @request.session[:user_id] = 2
3302 3313 get :bulk_edit, :ids => [1, 2, 6]
3303 3314 assert_response :success
3304 3315 assert_template 'bulk_edit'
3305 3316
3306 3317 # Can not set issues from different projects as children of an issue
3307 3318 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
3308 3319
3309 3320 # Project specific custom field, date type
3310 3321 field = CustomField.find(9)
3311 3322 assert !field.is_for_all?
3312 3323 assert !field.project_ids.include?(Issue.find(6).project_id)
3313 3324 assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
3314 3325 end
3315 3326
3316 3327 def test_get_bulk_edit_with_user_custom_field
3317 3328 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true)
3318 3329
3319 3330 @request.session[:user_id] = 2
3320 3331 get :bulk_edit, :ids => [1, 2]
3321 3332 assert_response :success
3322 3333 assert_template 'bulk_edit'
3323 3334
3324 3335 assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3325 3336 assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
3326 3337 end
3327 3338 end
3328 3339
3329 3340 def test_get_bulk_edit_with_version_custom_field
3330 3341 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true)
3331 3342
3332 3343 @request.session[:user_id] = 2
3333 3344 get :bulk_edit, :ids => [1, 2]
3334 3345 assert_response :success
3335 3346 assert_template 'bulk_edit'
3336 3347
3337 3348 assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3338 3349 assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
3339 3350 end
3340 3351 end
3341 3352
3342 3353 def test_get_bulk_edit_with_multi_custom_field
3343 3354 field = CustomField.find(1)
3344 3355 field.update_attribute :multiple, true
3345 3356
3346 3357 @request.session[:user_id] = 2
3347 3358 get :bulk_edit, :ids => [1, 2]
3348 3359 assert_response :success
3349 3360 assert_template 'bulk_edit'
3350 3361
3351 3362 assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
3352 3363 assert_select 'option', field.possible_values.size + 1 # "none" options
3353 3364 end
3354 3365 end
3355 3366
3356 3367 def test_bulk_edit_should_propose_to_clear_text_custom_fields
3357 3368 @request.session[:user_id] = 2
3358 3369 get :bulk_edit, :ids => [1, 3]
3359 3370 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
3360 3371 end
3361 3372
3362 3373 def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
3363 3374 WorkflowTransition.delete_all
3364 3375 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3365 3376 :old_status_id => 1, :new_status_id => 1)
3366 3377 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3367 3378 :old_status_id => 1, :new_status_id => 3)
3368 3379 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3369 3380 :old_status_id => 1, :new_status_id => 4)
3370 3381 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3371 3382 :old_status_id => 2, :new_status_id => 1)
3372 3383 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3373 3384 :old_status_id => 2, :new_status_id => 3)
3374 3385 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3375 3386 :old_status_id => 2, :new_status_id => 5)
3376 3387 @request.session[:user_id] = 2
3377 3388 get :bulk_edit, :ids => [1, 2]
3378 3389
3379 3390 assert_response :success
3380 3391 statuses = assigns(:available_statuses)
3381 3392 assert_not_nil statuses
3382 3393 assert_equal [1, 3], statuses.map(&:id).sort
3383 3394
3384 3395 assert_select 'select[name=?]', 'issue[status_id]' do
3385 3396 assert_select 'option', 3 # 2 statuses + "no change" option
3386 3397 end
3387 3398 end
3388 3399
3389 3400 def test_bulk_edit_should_propose_target_project_open_shared_versions
3390 3401 @request.session[:user_id] = 2
3391 3402 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3392 3403 assert_response :success
3393 3404 assert_template 'bulk_edit'
3394 3405 assert_equal Project.find(1).shared_versions.open.all.sort, assigns(:versions).sort
3395 3406
3396 3407 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
3397 3408 assert_select 'option', :text => '2.0'
3398 3409 end
3399 3410 end
3400 3411
3401 3412 def test_bulk_edit_should_propose_target_project_categories
3402 3413 @request.session[:user_id] = 2
3403 3414 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3404 3415 assert_response :success
3405 3416 assert_template 'bulk_edit'
3406 3417 assert_equal Project.find(1).issue_categories.sort, assigns(:categories).sort
3407 3418
3408 3419 assert_select 'select[name=?]', 'issue[category_id]' do
3409 3420 assert_select 'option', :text => 'Recipes'
3410 3421 end
3411 3422 end
3412 3423
3413 3424 def test_bulk_update
3414 3425 @request.session[:user_id] = 2
3415 3426 # update issues priority
3416 3427 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
3417 3428 :issue => {:priority_id => 7,
3418 3429 :assigned_to_id => '',
3419 3430 :custom_field_values => {'2' => ''}}
3420 3431
3421 3432 assert_response 302
3422 3433 # check that the issues were updated
3423 3434 assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id}
3424 3435
3425 3436 issue = Issue.find(1)
3426 3437 journal = issue.journals.reorder('created_on DESC').first
3427 3438 assert_equal '125', issue.custom_value_for(2).value
3428 3439 assert_equal 'Bulk editing', journal.notes
3429 3440 assert_equal 1, journal.details.size
3430 3441 end
3431 3442
3432 3443 def test_bulk_update_with_group_assignee
3433 3444 group = Group.find(11)
3434 3445 project = Project.find(1)
3435 3446 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
3436 3447
3437 3448 @request.session[:user_id] = 2
3438 3449 # update issues assignee
3439 3450 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
3440 3451 :issue => {:priority_id => '',
3441 3452 :assigned_to_id => group.id,
3442 3453 :custom_field_values => {'2' => ''}}
3443 3454
3444 3455 assert_response 302
3445 3456 assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
3446 3457 end
3447 3458
3448 3459 def test_bulk_update_on_different_projects
3449 3460 @request.session[:user_id] = 2
3450 3461 # update issues priority
3451 3462 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
3452 3463 :issue => {:priority_id => 7,
3453 3464 :assigned_to_id => '',
3454 3465 :custom_field_values => {'2' => ''}}
3455 3466
3456 3467 assert_response 302
3457 3468 # check that the issues were updated
3458 3469 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
3459 3470
3460 3471 issue = Issue.find(1)
3461 3472 journal = issue.journals.reorder('created_on DESC').first
3462 3473 assert_equal '125', issue.custom_value_for(2).value
3463 3474 assert_equal 'Bulk editing', journal.notes
3464 3475 assert_equal 1, journal.details.size
3465 3476 end
3466 3477
3467 3478 def test_bulk_update_on_different_projects_without_rights
3468 3479 @request.session[:user_id] = 3
3469 3480 user = User.find(3)
3470 3481 action = { :controller => "issues", :action => "bulk_update" }
3471 3482 assert user.allowed_to?(action, Issue.find(1).project)
3472 3483 assert ! user.allowed_to?(action, Issue.find(6).project)
3473 3484 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
3474 3485 :issue => {:priority_id => 7,
3475 3486 :assigned_to_id => '',
3476 3487 :custom_field_values => {'2' => ''}}
3477 3488 assert_response 403
3478 3489 assert_not_equal "Bulk should fail", Journal.last.notes
3479 3490 end
3480 3491
3481 3492 def test_bullk_update_should_send_a_notification
3482 3493 @request.session[:user_id] = 2
3483 3494 ActionMailer::Base.deliveries.clear
3484 3495 post(:bulk_update,
3485 3496 {
3486 3497 :ids => [1, 2],
3487 3498 :notes => 'Bulk editing',
3488 3499 :issue => {
3489 3500 :priority_id => 7,
3490 3501 :assigned_to_id => '',
3491 3502 :custom_field_values => {'2' => ''}
3492 3503 }
3493 3504 })
3494 3505
3495 3506 assert_response 302
3496 3507 assert_equal 2, ActionMailer::Base.deliveries.size
3497 3508 end
3498 3509
3499 3510 def test_bulk_update_project
3500 3511 @request.session[:user_id] = 2
3501 3512 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
3502 3513 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3503 3514 # Issues moved to project 2
3504 3515 assert_equal 2, Issue.find(1).project_id
3505 3516 assert_equal 2, Issue.find(2).project_id
3506 3517 # No tracker change
3507 3518 assert_equal 1, Issue.find(1).tracker_id
3508 3519 assert_equal 2, Issue.find(2).tracker_id
3509 3520 end
3510 3521
3511 3522 def test_bulk_update_project_on_single_issue_should_follow_when_needed
3512 3523 @request.session[:user_id] = 2
3513 3524 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
3514 3525 assert_redirected_to '/issues/1'
3515 3526 end
3516 3527
3517 3528 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
3518 3529 @request.session[:user_id] = 2
3519 3530 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
3520 3531 assert_redirected_to '/projects/onlinestore/issues'
3521 3532 end
3522 3533
3523 3534 def test_bulk_update_tracker
3524 3535 @request.session[:user_id] = 2
3525 3536 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
3526 3537 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3527 3538 assert_equal 2, Issue.find(1).tracker_id
3528 3539 assert_equal 2, Issue.find(2).tracker_id
3529 3540 end
3530 3541
3531 3542 def test_bulk_update_status
3532 3543 @request.session[:user_id] = 2
3533 3544 # update issues priority
3534 3545 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
3535 3546 :issue => {:priority_id => '',
3536 3547 :assigned_to_id => '',
3537 3548 :status_id => '5'}
3538 3549
3539 3550 assert_response 302
3540 3551 issue = Issue.find(1)
3541 3552 assert issue.closed?
3542 3553 end
3543 3554
3544 3555 def test_bulk_update_priority
3545 3556 @request.session[:user_id] = 2
3546 3557 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
3547 3558
3548 3559 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3549 3560 assert_equal 6, Issue.find(1).priority_id
3550 3561 assert_equal 6, Issue.find(2).priority_id
3551 3562 end
3552 3563
3553 3564 def test_bulk_update_with_notes
3554 3565 @request.session[:user_id] = 2
3555 3566 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
3556 3567
3557 3568 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3558 3569 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
3559 3570 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
3560 3571 end
3561 3572
3562 3573 def test_bulk_update_parent_id
3563 3574 IssueRelation.delete_all
3564 3575 @request.session[:user_id] = 2
3565 3576 post :bulk_update, :ids => [1, 3],
3566 3577 :notes => 'Bulk editing parent',
3567 3578 :issue => {:priority_id => '', :assigned_to_id => '',
3568 3579 :status_id => '', :parent_issue_id => '2'}
3569 3580 assert_response 302
3570 3581 parent = Issue.find(2)
3571 3582 assert_equal parent.id, Issue.find(1).parent_id
3572 3583 assert_equal parent.id, Issue.find(3).parent_id
3573 3584 assert_equal [1, 3], parent.children.collect(&:id).sort
3574 3585 end
3575 3586
3576 3587 def test_bulk_update_custom_field
3577 3588 @request.session[:user_id] = 2
3578 3589 # update issues priority
3579 3590 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
3580 3591 :issue => {:priority_id => '',
3581 3592 :assigned_to_id => '',
3582 3593 :custom_field_values => {'2' => '777'}}
3583 3594
3584 3595 assert_response 302
3585 3596
3586 3597 issue = Issue.find(1)
3587 3598 journal = issue.journals.reorder('created_on DESC').first
3588 3599 assert_equal '777', issue.custom_value_for(2).value
3589 3600 assert_equal 1, journal.details.size
3590 3601 assert_equal '125', journal.details.first.old_value
3591 3602 assert_equal '777', journal.details.first.value
3592 3603 end
3593 3604
3594 3605 def test_bulk_update_custom_field_to_blank
3595 3606 @request.session[:user_id] = 2
3596 3607 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
3597 3608 :issue => {:priority_id => '',
3598 3609 :assigned_to_id => '',
3599 3610 :custom_field_values => {'1' => '__none__'}}
3600 3611 assert_response 302
3601 3612 assert_equal '', Issue.find(1).custom_field_value(1)
3602 3613 assert_equal '', Issue.find(3).custom_field_value(1)
3603 3614 end
3604 3615
3605 3616 def test_bulk_update_multi_custom_field
3606 3617 field = CustomField.find(1)
3607 3618 field.update_attribute :multiple, true
3608 3619
3609 3620 @request.session[:user_id] = 2
3610 3621 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
3611 3622 :issue => {:priority_id => '',
3612 3623 :assigned_to_id => '',
3613 3624 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
3614 3625
3615 3626 assert_response 302
3616 3627
3617 3628 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
3618 3629 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
3619 3630 # the custom field is not associated with the issue tracker
3620 3631 assert_nil Issue.find(2).custom_field_value(1)
3621 3632 end
3622 3633
3623 3634 def test_bulk_update_multi_custom_field_to_blank
3624 3635 field = CustomField.find(1)
3625 3636 field.update_attribute :multiple, true
3626 3637
3627 3638 @request.session[:user_id] = 2
3628 3639 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
3629 3640 :issue => {:priority_id => '',
3630 3641 :assigned_to_id => '',
3631 3642 :custom_field_values => {'1' => ['__none__']}}
3632 3643 assert_response 302
3633 3644 assert_equal [''], Issue.find(1).custom_field_value(1)
3634 3645 assert_equal [''], Issue.find(3).custom_field_value(1)
3635 3646 end
3636 3647
3637 3648 def test_bulk_update_unassign
3638 3649 assert_not_nil Issue.find(2).assigned_to
3639 3650 @request.session[:user_id] = 2
3640 3651 # unassign issues
3641 3652 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
3642 3653 assert_response 302
3643 3654 # check that the issues were updated
3644 3655 assert_nil Issue.find(2).assigned_to
3645 3656 end
3646 3657
3647 3658 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
3648 3659 @request.session[:user_id] = 2
3649 3660
3650 3661 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
3651 3662
3652 3663 assert_response :redirect
3653 3664 issues = Issue.find([1,2])
3654 3665 issues.each do |issue|
3655 3666 assert_equal 4, issue.fixed_version_id
3656 3667 assert_not_equal issue.project_id, issue.fixed_version.project_id
3657 3668 end
3658 3669 end
3659 3670
3660 3671 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
3661 3672 @request.session[:user_id] = 2
3662 3673 post :bulk_update, :ids => [1,2], :back_url => '/issues'
3663 3674
3664 3675 assert_response :redirect
3665 3676 assert_redirected_to '/issues'
3666 3677 end
3667 3678
3668 3679 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3669 3680 @request.session[:user_id] = 2
3670 3681 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
3671 3682
3672 3683 assert_response :redirect
3673 3684 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
3674 3685 end
3675 3686
3676 3687 def test_bulk_update_with_all_failures_should_show_errors
3677 3688 @request.session[:user_id] = 2
3678 3689 post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
3679 3690
3680 3691 assert_response :success
3681 3692 assert_template 'bulk_edit'
3682 3693 assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
3683 3694 assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
3684 3695
3685 3696 assert_equal [1, 2], assigns[:issues].map(&:id)
3686 3697 end
3687 3698
3688 3699 def test_bulk_update_with_some_failures_should_show_errors
3689 3700 issue1 = Issue.generate!(:start_date => '2013-05-12')
3690 3701 issue2 = Issue.generate!(:start_date => '2013-05-15')
3691 3702 issue3 = Issue.generate!
3692 3703 @request.session[:user_id] = 2
3693 3704 post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id],
3694 3705 :issue => {:due_date => '2013-05-01'}
3695 3706 assert_response :success
3696 3707 assert_template 'bulk_edit'
3697 3708 assert_select '#errorExplanation span',
3698 3709 :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
3699 3710 assert_select '#errorExplanation ul li',
3700 3711 :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
3701 3712 assert_equal [issue1.id, issue2.id], assigns[:issues].map(&:id)
3702 3713 end
3703 3714
3704 3715 def test_bulk_update_with_failure_should_preserved_form_values
3705 3716 @request.session[:user_id] = 2
3706 3717 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2', :start_date => 'foo'}
3707 3718
3708 3719 assert_response :success
3709 3720 assert_template 'bulk_edit'
3710 3721 assert_select 'select[name=?]', 'issue[tracker_id]' do
3711 3722 assert_select 'option[value=2][selected=selected]'
3712 3723 end
3713 3724 assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
3714 3725 end
3715 3726
3716 3727 def test_get_bulk_copy
3717 3728 @request.session[:user_id] = 2
3718 3729 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
3719 3730 assert_response :success
3720 3731 assert_template 'bulk_edit'
3721 3732
3722 3733 issues = assigns(:issues)
3723 3734 assert_not_nil issues
3724 3735 assert_equal [1, 2, 3], issues.map(&:id).sort
3725 3736
3726 3737 assert_select 'input[name=copy_attachments]'
3727 3738 end
3728 3739
3729 3740 def test_bulk_copy_to_another_project
3730 3741 @request.session[:user_id] = 2
3731 3742 assert_difference 'Issue.count', 2 do
3732 3743 assert_no_difference 'Project.find(1).issues.count' do
3733 3744 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
3734 3745 end
3735 3746 end
3736 3747 assert_redirected_to '/projects/ecookbook/issues'
3737 3748
3738 3749 copies = Issue.order('id DESC').limit(issues.size)
3739 3750 copies.each do |copy|
3740 3751 assert_equal 2, copy.project_id
3741 3752 end
3742 3753 end
3743 3754
3744 3755 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
3745 3756 @request.session[:user_id] = 2
3746 3757 issues = [
3747 3758 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
3748 3759 :priority_id => 2, :subject => 'issue 1', :author_id => 1,
3749 3760 :assigned_to_id => nil),
3750 3761 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
3751 3762 :priority_id => 1, :subject => 'issue 2', :author_id => 2,
3752 3763 :assigned_to_id => 3)
3753 3764 ]
3754 3765 assert_difference 'Issue.count', issues.size do
3755 3766 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
3756 3767 :issue => {
3757 3768 :project_id => '', :tracker_id => '', :assigned_to_id => '',
3758 3769 :status_id => '', :start_date => '', :due_date => ''
3759 3770 }
3760 3771 end
3761 3772
3762 3773 copies = Issue.order('id DESC').limit(issues.size)
3763 3774 issues.each do |orig|
3764 3775 copy = copies.detect {|c| c.subject == orig.subject}
3765 3776 assert_not_nil copy
3766 3777 assert_equal orig.project_id, copy.project_id
3767 3778 assert_equal orig.tracker_id, copy.tracker_id
3768 3779 assert_equal orig.status_id, copy.status_id
3769 3780 assert_equal orig.assigned_to_id, copy.assigned_to_id
3770 3781 assert_equal orig.priority_id, copy.priority_id
3771 3782 end
3772 3783 end
3773 3784
3774 3785 def test_bulk_copy_should_allow_changing_the_issue_attributes
3775 3786 # Fixes random test failure with Mysql
3776 3787 # where Issue.where(:project_id => 2).limit(2).order('id desc')
3777 3788 # doesn't return the expected results
3778 3789 Issue.delete_all("project_id=2")
3779 3790
3780 3791 @request.session[:user_id] = 2
3781 3792 assert_difference 'Issue.count', 2 do
3782 3793 assert_no_difference 'Project.find(1).issues.count' do
3783 3794 post :bulk_update, :ids => [1, 2], :copy => '1',
3784 3795 :issue => {
3785 3796 :project_id => '2', :tracker_id => '', :assigned_to_id => '4',
3786 3797 :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
3787 3798 }
3788 3799 end
3789 3800 end
3790 3801
3791 3802 copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
3792 3803 assert_equal 2, copied_issues.size
3793 3804 copied_issues.each do |issue|
3794 3805 assert_equal 2, issue.project_id, "Project is incorrect"
3795 3806 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
3796 3807 assert_equal 1, issue.status_id, "Status is incorrect"
3797 3808 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
3798 3809 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
3799 3810 end
3800 3811 end
3801 3812
3802 3813 def test_bulk_copy_should_allow_adding_a_note
3803 3814 @request.session[:user_id] = 2
3804 3815 assert_difference 'Issue.count', 1 do
3805 3816 post :bulk_update, :ids => [1], :copy => '1',
3806 3817 :notes => 'Copying one issue',
3807 3818 :issue => {
3808 3819 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
3809 3820 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
3810 3821 }
3811 3822 end
3812 3823 issue = Issue.order('id DESC').first
3813 3824 assert_equal 1, issue.journals.size
3814 3825 journal = issue.journals.first
3815 3826 assert_equal 1, journal.details.size
3816 3827 assert_equal 'Copying one issue', journal.notes
3817 3828 end
3818 3829
3819 3830 def test_bulk_copy_should_allow_not_copying_the_attachments
3820 3831 attachment_count = Issue.find(3).attachments.size
3821 3832 assert attachment_count > 0
3822 3833 @request.session[:user_id] = 2
3823 3834
3824 3835 assert_difference 'Issue.count', 1 do
3825 3836 assert_no_difference 'Attachment.count' do
3826 3837 post :bulk_update, :ids => [3], :copy => '1',
3827 3838 :issue => {
3828 3839 :project_id => ''
3829 3840 }
3830 3841 end
3831 3842 end
3832 3843 end
3833 3844
3834 3845 def test_bulk_copy_should_allow_copying_the_attachments
3835 3846 attachment_count = Issue.find(3).attachments.size
3836 3847 assert attachment_count > 0
3837 3848 @request.session[:user_id] = 2
3838 3849
3839 3850 assert_difference 'Issue.count', 1 do
3840 3851 assert_difference 'Attachment.count', attachment_count do
3841 3852 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
3842 3853 :issue => {
3843 3854 :project_id => ''
3844 3855 }
3845 3856 end
3846 3857 end
3847 3858 end
3848 3859
3849 3860 def test_bulk_copy_should_add_relations_with_copied_issues
3850 3861 @request.session[:user_id] = 2
3851 3862
3852 3863 assert_difference 'Issue.count', 2 do
3853 3864 assert_difference 'IssueRelation.count', 2 do
3854 3865 post :bulk_update, :ids => [1, 3], :copy => '1',
3855 3866 :issue => {
3856 3867 :project_id => '1'
3857 3868 }
3858 3869 end
3859 3870 end
3860 3871 end
3861 3872
3862 3873 def test_bulk_copy_should_allow_not_copying_the_subtasks
3863 3874 issue = Issue.generate_with_descendants!
3864 3875 @request.session[:user_id] = 2
3865 3876
3866 3877 assert_difference 'Issue.count', 1 do
3867 3878 post :bulk_update, :ids => [issue.id], :copy => '1',
3868 3879 :issue => {
3869 3880 :project_id => ''
3870 3881 }
3871 3882 end
3872 3883 end
3873 3884
3874 3885 def test_bulk_copy_should_allow_copying_the_subtasks
3875 3886 issue = Issue.generate_with_descendants!
3876 3887 count = issue.descendants.count
3877 3888 @request.session[:user_id] = 2
3878 3889
3879 3890 assert_difference 'Issue.count', count+1 do
3880 3891 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
3881 3892 :issue => {
3882 3893 :project_id => ''
3883 3894 }
3884 3895 end
3885 3896 copy = Issue.where(:parent_id => nil).order("id DESC").first
3886 3897 assert_equal count, copy.descendants.count
3887 3898 end
3888 3899
3889 3900 def test_bulk_copy_should_not_copy_selected_subtasks_twice
3890 3901 issue = Issue.generate_with_descendants!
3891 3902 count = issue.descendants.count
3892 3903 @request.session[:user_id] = 2
3893 3904
3894 3905 assert_difference 'Issue.count', count+1 do
3895 3906 post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
3896 3907 :issue => {
3897 3908 :project_id => ''
3898 3909 }
3899 3910 end
3900 3911 copy = Issue.where(:parent_id => nil).order("id DESC").first
3901 3912 assert_equal count, copy.descendants.count
3902 3913 end
3903 3914
3904 3915 def test_bulk_copy_to_another_project_should_follow_when_needed
3905 3916 @request.session[:user_id] = 2
3906 3917 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
3907 3918 issue = Issue.order('id DESC').first
3908 3919 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
3909 3920 end
3910 3921
3911 3922 def test_bulk_copy_with_all_failures_should_display_errors
3912 3923 @request.session[:user_id] = 2
3913 3924 post :bulk_update, :ids => [1, 2], :copy => '1', :issue => {:start_date => 'foo'}
3914 3925
3915 3926 assert_response :success
3916 3927 end
3917 3928
3918 3929 def test_destroy_issue_with_no_time_entries
3919 3930 assert_nil TimeEntry.find_by_issue_id(2)
3920 3931 @request.session[:user_id] = 2
3921 3932
3922 3933 assert_difference 'Issue.count', -1 do
3923 3934 delete :destroy, :id => 2
3924 3935 end
3925 3936 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3926 3937 assert_nil Issue.find_by_id(2)
3927 3938 end
3928 3939
3929 3940 def test_destroy_issues_with_time_entries
3930 3941 @request.session[:user_id] = 2
3931 3942
3932 3943 assert_no_difference 'Issue.count' do
3933 3944 delete :destroy, :ids => [1, 3]
3934 3945 end
3935 3946 assert_response :success
3936 3947 assert_template 'destroy'
3937 3948 assert_not_nil assigns(:hours)
3938 3949 assert Issue.find_by_id(1) && Issue.find_by_id(3)
3939 3950
3940 3951 assert_select 'form' do
3941 3952 assert_select 'input[name=_method][value=delete]'
3942 3953 end
3943 3954 end
3944 3955
3945 3956 def test_destroy_issues_and_destroy_time_entries
3946 3957 @request.session[:user_id] = 2
3947 3958
3948 3959 assert_difference 'Issue.count', -2 do
3949 3960 assert_difference 'TimeEntry.count', -3 do
3950 3961 delete :destroy, :ids => [1, 3], :todo => 'destroy'
3951 3962 end
3952 3963 end
3953 3964 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3954 3965 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3955 3966 assert_nil TimeEntry.find_by_id([1, 2])
3956 3967 end
3957 3968
3958 3969 def test_destroy_issues_and_assign_time_entries_to_project
3959 3970 @request.session[:user_id] = 2
3960 3971
3961 3972 assert_difference 'Issue.count', -2 do
3962 3973 assert_no_difference 'TimeEntry.count' do
3963 3974 delete :destroy, :ids => [1, 3], :todo => 'nullify'
3964 3975 end
3965 3976 end
3966 3977 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3967 3978 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3968 3979 assert_nil TimeEntry.find(1).issue_id
3969 3980 assert_nil TimeEntry.find(2).issue_id
3970 3981 end
3971 3982
3972 3983 def test_destroy_issues_and_reassign_time_entries_to_another_issue
3973 3984 @request.session[:user_id] = 2
3974 3985
3975 3986 assert_difference 'Issue.count', -2 do
3976 3987 assert_no_difference 'TimeEntry.count' do
3977 3988 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
3978 3989 end
3979 3990 end
3980 3991 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3981 3992 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3982 3993 assert_equal 2, TimeEntry.find(1).issue_id
3983 3994 assert_equal 2, TimeEntry.find(2).issue_id
3984 3995 end
3985 3996
3986 3997 def test_destroy_issues_from_different_projects
3987 3998 @request.session[:user_id] = 2
3988 3999
3989 4000 assert_difference 'Issue.count', -3 do
3990 4001 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
3991 4002 end
3992 4003 assert_redirected_to :controller => 'issues', :action => 'index'
3993 4004 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
3994 4005 end
3995 4006
3996 4007 def test_destroy_parent_and_child_issues
3997 4008 parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
3998 4009 child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
3999 4010 assert child.is_descendant_of?(parent.reload)
4000 4011
4001 4012 @request.session[:user_id] = 2
4002 4013 assert_difference 'Issue.count', -2 do
4003 4014 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
4004 4015 end
4005 4016 assert_response 302
4006 4017 end
4007 4018
4008 4019 def test_destroy_invalid_should_respond_with_404
4009 4020 @request.session[:user_id] = 2
4010 4021 assert_no_difference 'Issue.count' do
4011 4022 delete :destroy, :id => 999
4012 4023 end
4013 4024 assert_response 404
4014 4025 end
4015 4026
4016 4027 def test_default_search_scope
4017 4028 get :index
4018 4029
4019 4030 assert_select 'div#quick-search form' do
4020 4031 assert_select 'input[name=issues][value=1][type=hidden]'
4021 4032 end
4022 4033 end
4023 4034 end
General Comments 0
You need to be logged in to leave comments. Login now