##// END OF EJS Templates
Fixed rounding issue on spent hours column in CSV export (#10150)....
Jean-Philippe Lang -
r8644:333a6cc37005
parent child
Show More
@@ -1,345 +1,345
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2011 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 IssuesHelper
21 21 include ApplicationHelper
22 22
23 23 def issue_list(issues, &block)
24 24 ancestors = []
25 25 issues.each do |issue|
26 26 while (ancestors.any? && !issue.is_descendant_of?(ancestors.last))
27 27 ancestors.pop
28 28 end
29 29 yield issue, ancestors.size
30 30 ancestors << issue unless issue.leaf?
31 31 end
32 32 end
33 33
34 34 # Renders a HTML/CSS tooltip
35 35 #
36 36 # To use, a trigger div is needed. This is a div with the class of "tooltip"
37 37 # that contains this method wrapped in a span with the class of "tip"
38 38 #
39 39 # <div class="tooltip"><%= link_to_issue(issue) %>
40 40 # <span class="tip"><%= render_issue_tooltip(issue) %></span>
41 41 # </div>
42 42 #
43 43 def render_issue_tooltip(issue)
44 44 @cached_label_status ||= l(:field_status)
45 45 @cached_label_start_date ||= l(:field_start_date)
46 46 @cached_label_due_date ||= l(:field_due_date)
47 47 @cached_label_assigned_to ||= l(:field_assigned_to)
48 48 @cached_label_priority ||= l(:field_priority)
49 49 @cached_label_project ||= l(:field_project)
50 50
51 51 link_to_issue(issue) + "<br /><br />".html_safe +
52 52 "<strong>#{@cached_label_project}</strong>: #{link_to_project(issue.project)}<br />".html_safe +
53 53 "<strong>#{@cached_label_status}</strong>: #{h(issue.status.name)}<br />".html_safe +
54 54 "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />".html_safe +
55 55 "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />".html_safe +
56 56 "<strong>#{@cached_label_assigned_to}</strong>: #{h(issue.assigned_to)}<br />".html_safe +
57 57 "<strong>#{@cached_label_priority}</strong>: #{h(issue.priority.name)}".html_safe
58 58 end
59 59
60 60 def issue_heading(issue)
61 61 h("#{issue.tracker} ##{issue.id}")
62 62 end
63 63
64 64 def render_issue_subject_with_tree(issue)
65 65 s = ''
66 66 ancestors = issue.root? ? [] : issue.ancestors.visible.all
67 67 ancestors.each do |ancestor|
68 68 s << '<div>' + content_tag('p', link_to_issue(ancestor))
69 69 end
70 70 s << '<div>'
71 71 subject = h(issue.subject)
72 72 if issue.is_private?
73 73 subject = content_tag('span', l(:field_is_private), :class => 'private') + ' ' + subject
74 74 end
75 75 s << content_tag('h3', subject)
76 76 s << '</div>' * (ancestors.size + 1)
77 77 s.html_safe
78 78 end
79 79
80 80 def render_descendants_tree(issue)
81 81 s = '<form><table class="list issues">'
82 82 issue_list(issue.descendants.visible.sort_by(&:lft)) do |child, level|
83 83 s << content_tag('tr',
84 84 content_tag('td', check_box_tag("ids[]", child.id, false, :id => nil), :class => 'checkbox') +
85 85 content_tag('td', link_to_issue(child, :truncate => 60), :class => 'subject') +
86 86 content_tag('td', h(child.status)) +
87 87 content_tag('td', link_to_user(child.assigned_to)) +
88 88 content_tag('td', progress_bar(child.done_ratio, :width => '80px')),
89 89 :class => "issue issue-#{child.id} hascontextmenu #{level > 0 ? "idnt idnt-#{level}" : nil}")
90 90 end
91 91 s << '</table></form>'
92 92 s.html_safe
93 93 end
94 94
95 95 def render_custom_fields_rows(issue)
96 96 return if issue.custom_field_values.empty?
97 97 ordered_values = []
98 98 half = (issue.custom_field_values.size / 2.0).ceil
99 99 half.times do |i|
100 100 ordered_values << issue.custom_field_values[i]
101 101 ordered_values << issue.custom_field_values[i + half]
102 102 end
103 103 s = "<tr>\n"
104 104 n = 0
105 105 ordered_values.compact.each do |value|
106 106 s << "</tr>\n<tr>\n" if n > 0 && (n % 2) == 0
107 107 s << "\t<th>#{ h(value.custom_field.name) }:</th><td>#{ simple_format_without_paragraph(h(show_value(value))) }</td>\n"
108 108 n += 1
109 109 end
110 110 s << "</tr>\n"
111 111 s.html_safe
112 112 end
113 113
114 114 def issues_destroy_confirmation_message(issues)
115 115 issues = [issues] unless issues.is_a?(Array)
116 116 message = l(:text_issues_destroy_confirmation)
117 117 descendant_count = issues.inject(0) {|memo, i| memo += (i.right - i.left - 1)/2}
118 118 if descendant_count > 0
119 119 issues.each do |issue|
120 120 next if issue.root?
121 121 issues.each do |other_issue|
122 122 descendant_count -= 1 if issue.is_descendant_of?(other_issue)
123 123 end
124 124 end
125 125 if descendant_count > 0
126 126 message << "\n" + l(:text_issues_destroy_descendants_confirmation, :count => descendant_count)
127 127 end
128 128 end
129 129 message
130 130 end
131 131
132 132 def sidebar_queries
133 133 unless @sidebar_queries
134 134 @sidebar_queries = Query.visible.all(
135 135 :order => "#{Query.table_name}.name ASC",
136 136 # Project specific queries and global queries
137 137 :conditions => (@project.nil? ? ["project_id IS NULL"] : ["project_id IS NULL OR project_id = ?", @project.id])
138 138 )
139 139 end
140 140 @sidebar_queries
141 141 end
142 142
143 143 def query_links(title, queries)
144 144 # links to #index on issues/show
145 145 url_params = controller_name == 'issues' ? {:controller => 'issues', :action => 'index', :project_id => @project} : params
146 146
147 147 content_tag('h3', h(title)) +
148 148 queries.collect {|query|
149 149 css = 'query'
150 150 css << ' selected' if query == @query
151 151 link_to(h(query.name), url_params.merge(:query_id => query), :class => css)
152 152 }.join('<br />').html_safe
153 153 end
154 154
155 155 def render_sidebar_queries
156 156 out = ''.html_safe
157 157 queries = sidebar_queries.select {|q| !q.is_public?}
158 158 out << query_links(l(:label_my_queries), queries) if queries.any?
159 159 queries = sidebar_queries.select {|q| q.is_public?}
160 160 out << query_links(l(:label_query_plural), queries) if queries.any?
161 161 out
162 162 end
163 163
164 164 # Returns the textual representation of a journal details
165 165 # as an array of strings
166 166 def details_to_strings(details, no_html=false)
167 167 strings = []
168 168 values_by_field = {}
169 169 details.each do |detail|
170 170 if detail.property == 'cf'
171 171 field_id = detail.prop_key
172 172 field = CustomField.find_by_id(field_id)
173 173 if field && field.multiple?
174 174 values_by_field[field_id] ||= {:added => [], :deleted => []}
175 175 if detail.old_value
176 176 values_by_field[field_id][:deleted] << detail.old_value
177 177 end
178 178 if detail.value
179 179 values_by_field[field_id][:added] << detail.value
180 180 end
181 181 next
182 182 end
183 183 end
184 184 strings << show_detail(detail, no_html)
185 185 end
186 186 values_by_field.each do |field_id, changes|
187 187 detail = JournalDetail.new(:property => 'cf', :prop_key => field_id)
188 188 if changes[:added].any?
189 189 detail.value = changes[:added]
190 190 strings << show_detail(detail, no_html)
191 191 elsif changes[:deleted].any?
192 192 detail.old_value = changes[:deleted]
193 193 strings << show_detail(detail, no_html)
194 194 end
195 195 end
196 196 strings
197 197 end
198 198
199 199 # Returns the textual representation of a single journal detail
200 200 def show_detail(detail, no_html=false)
201 201 multiple = false
202 202 case detail.property
203 203 when 'attr'
204 204 field = detail.prop_key.to_s.gsub(/\_id$/, "")
205 205 label = l(("field_" + field).to_sym)
206 206 case detail.prop_key
207 207 when 'due_date', 'start_date'
208 208 value = format_date(detail.value.to_date) if detail.value
209 209 old_value = format_date(detail.old_value.to_date) if detail.old_value
210 210
211 211 when 'project_id', 'status_id', 'tracker_id', 'assigned_to_id',
212 212 'priority_id', 'category_id', 'fixed_version_id'
213 213 value = find_name_by_reflection(field, detail.value)
214 214 old_value = find_name_by_reflection(field, detail.old_value)
215 215
216 216 when 'estimated_hours'
217 217 value = "%0.02f" % detail.value.to_f unless detail.value.blank?
218 218 old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
219 219
220 220 when 'parent_id'
221 221 label = l(:field_parent_issue)
222 222 value = "##{detail.value}" unless detail.value.blank?
223 223 old_value = "##{detail.old_value}" unless detail.old_value.blank?
224 224
225 225 when 'is_private'
226 226 value = l(detail.value == "0" ? :general_text_No : :general_text_Yes) unless detail.value.blank?
227 227 old_value = l(detail.old_value == "0" ? :general_text_No : :general_text_Yes) unless detail.old_value.blank?
228 228 end
229 229 when 'cf'
230 230 custom_field = CustomField.find_by_id(detail.prop_key)
231 231 if custom_field
232 232 multiple = custom_field.multiple?
233 233 label = custom_field.name
234 234 value = format_value(detail.value, custom_field.field_format) if detail.value
235 235 old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
236 236 end
237 237 when 'attachment'
238 238 label = l(:label_attachment)
239 239 end
240 240 call_hook(:helper_issues_show_detail_after_setting,
241 241 {:detail => detail, :label => label, :value => value, :old_value => old_value })
242 242
243 243 label ||= detail.prop_key
244 244 value ||= detail.value
245 245 old_value ||= detail.old_value
246 246
247 247 unless no_html
248 248 label = content_tag('strong', label)
249 249 old_value = content_tag("i", h(old_value)) if detail.old_value
250 250 old_value = content_tag("strike", old_value) if detail.old_value and detail.value.blank?
251 251 if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
252 252 # Link to the attachment if it has not been removed
253 253 value = link_to_attachment(a, :download => true)
254 254 else
255 255 value = content_tag("i", h(value)) if value
256 256 end
257 257 end
258 258
259 259 if detail.property == 'attr' && detail.prop_key == 'description'
260 260 s = l(:text_journal_changed_no_detail, :label => label)
261 261 unless no_html
262 262 diff_link = link_to 'diff',
263 263 {:controller => 'journals', :action => 'diff', :id => detail.journal_id, :detail_id => detail.id},
264 264 :title => l(:label_view_diff)
265 265 s << " (#{ diff_link })"
266 266 end
267 267 s.html_safe
268 268 elsif detail.value.present?
269 269 case detail.property
270 270 when 'attr', 'cf'
271 271 if detail.old_value.present?
272 272 l(:text_journal_changed, :label => label, :old => old_value, :new => value).html_safe
273 273 elsif multiple
274 274 l(:text_journal_added, :label => label, :value => value).html_safe
275 275 else
276 276 l(:text_journal_set_to, :label => label, :value => value).html_safe
277 277 end
278 278 when 'attachment'
279 279 l(:text_journal_added, :label => label, :value => value).html_safe
280 280 end
281 281 else
282 282 l(:text_journal_deleted, :label => label, :old => old_value).html_safe
283 283 end
284 284 end
285 285
286 286 # Find the name of an associated record stored in the field attribute
287 287 def find_name_by_reflection(field, id)
288 288 association = Issue.reflect_on_association(field.to_sym)
289 289 if association
290 290 record = association.class_name.constantize.find_by_id(id)
291 291 return record.name if record
292 292 end
293 293 end
294 294
295 295 # Renders issue children recursively
296 296 def render_api_issue_children(issue, api)
297 297 return if issue.leaf?
298 298 api.array :children do
299 299 issue.children.each do |child|
300 300 api.issue(:id => child.id) do
301 301 api.tracker(:id => child.tracker_id, :name => child.tracker.name) unless child.tracker.nil?
302 302 api.subject child.subject
303 303 render_api_issue_children(child, api)
304 304 end
305 305 end
306 306 end
307 307 end
308 308
309 309 def issues_to_csv(issues, project, query, options={})
310 310 decimal_separator = l(:general_csv_decimal_separator)
311 311 encoding = l(:general_csv_encoding)
312 312 columns = (options[:columns] == 'all' ? query.available_columns : query.columns)
313 313
314 314 export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv|
315 315 # csv header fields
316 316 csv << [ "#" ] + columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) } +
317 317 (options[:description] ? [Redmine::CodesetUtil.from_utf8(l(:field_description), encoding)] : [])
318 318
319 319 # csv lines
320 320 issues.each do |issue|
321 321 col_values = columns.collect do |column|
322 322 s = if column.is_a?(QueryCustomFieldColumn)
323 323 cv = issue.custom_field_values.detect {|v| v.custom_field_id == column.custom_field.id}
324 324 show_value(cv)
325 325 else
326 326 value = issue.send(column.name)
327 327 if value.is_a?(Date)
328 328 format_date(value)
329 329 elsif value.is_a?(Time)
330 330 format_time(value)
331 331 elsif value.is_a?(Float)
332 value.to_s.gsub('.', decimal_separator)
332 ("%.2f" % value).gsub('.', decimal_separator)
333 333 else
334 334 value
335 335 end
336 336 end
337 337 s.to_s
338 338 end
339 339 csv << [ issue.id.to_s ] + col_values.collect {|c| Redmine::CodesetUtil.from_utf8(c.to_s, encoding) } +
340 340 (options[:description] ? [Redmine::CodesetUtil.from_utf8(issue.description, encoding)] : [])
341 341 end
342 342 end
343 343 export
344 344 end
345 345 end
@@ -1,2928 +1,2939
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 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 require 'issues_controller'
20 20
21 21 class IssuesControllerTest < ActionController::TestCase
22 22 fixtures :projects,
23 23 :users,
24 24 :roles,
25 25 :members,
26 26 :member_roles,
27 27 :issues,
28 28 :issue_statuses,
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 @controller = IssuesController.new
52 52 @request = ActionController::TestRequest.new
53 53 @response = ActionController::TestResponse.new
54 54 User.current = nil
55 55 end
56 56
57 57 def test_index
58 58 Setting.default_language = 'en'
59 59
60 60 get :index
61 61 assert_response :success
62 62 assert_template 'index'
63 63 assert_not_nil assigns(:issues)
64 64 assert_nil assigns(:project)
65 65 assert_tag :tag => 'a', :content => /Can't print recipes/
66 66 assert_tag :tag => 'a', :content => /Subproject issue/
67 67 # private projects hidden
68 68 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
69 69 assert_no_tag :tag => 'a', :content => /Issue on project 2/
70 70 # project column
71 71 assert_tag :tag => 'th', :content => /Project/
72 72 end
73 73
74 74 def test_index_should_not_list_issues_when_module_disabled
75 75 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
76 76 get :index
77 77 assert_response :success
78 78 assert_template 'index'
79 79 assert_not_nil assigns(:issues)
80 80 assert_nil assigns(:project)
81 81 assert_no_tag :tag => 'a', :content => /Can't print recipes/
82 82 assert_tag :tag => 'a', :content => /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 assert_tag :tag => 'a', :content => /Can't print recipes/
99 99 assert_no_tag :tag => 'a', :content => /Subproject issue/
100 100 end
101 101
102 102 def test_index_with_project_and_subprojects
103 103 Setting.display_subprojects_issues = 1
104 104 get :index, :project_id => 1
105 105 assert_response :success
106 106 assert_template 'index'
107 107 assert_not_nil assigns(:issues)
108 108 assert_tag :tag => 'a', :content => /Can't print recipes/
109 109 assert_tag :tag => 'a', :content => /Subproject issue/
110 110 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
111 111 end
112 112
113 113 def test_index_with_project_and_subprojects_should_show_private_subprojects
114 114 @request.session[:user_id] = 2
115 115 Setting.display_subprojects_issues = 1
116 116 get :index, :project_id => 1
117 117 assert_response :success
118 118 assert_template 'index'
119 119 assert_not_nil assigns(:issues)
120 120 assert_tag :tag => 'a', :content => /Can't print recipes/
121 121 assert_tag :tag => 'a', :content => /Subproject issue/
122 122 assert_tag :tag => 'a', :content => /Issue of a private subproject/
123 123 end
124 124
125 125 def test_index_with_project_and_default_filter
126 126 get :index, :project_id => 1, :set_filter => 1
127 127 assert_response :success
128 128 assert_template 'index'
129 129 assert_not_nil assigns(:issues)
130 130
131 131 query = assigns(:query)
132 132 assert_not_nil query
133 133 # default filter
134 134 assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
135 135 end
136 136
137 137 def test_index_with_project_and_filter
138 138 get :index, :project_id => 1, :set_filter => 1,
139 139 :f => ['tracker_id'],
140 140 :op => {'tracker_id' => '='},
141 141 :v => {'tracker_id' => ['1']}
142 142 assert_response :success
143 143 assert_template 'index'
144 144 assert_not_nil assigns(:issues)
145 145
146 146 query = assigns(:query)
147 147 assert_not_nil query
148 148 assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
149 149 end
150 150
151 151 def test_index_with_short_filters
152 152
153 153 to_test = {
154 154 'status_id' => {
155 155 'o' => { :op => 'o', :values => [''] },
156 156 'c' => { :op => 'c', :values => [''] },
157 157 '7' => { :op => '=', :values => ['7'] },
158 158 '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
159 159 '=7' => { :op => '=', :values => ['7'] },
160 160 '!3' => { :op => '!', :values => ['3'] },
161 161 '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
162 162 'subject' => {
163 163 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
164 164 'o' => { :op => '=', :values => ['o'] },
165 165 '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
166 166 '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
167 167 'tracker_id' => {
168 168 '3' => { :op => '=', :values => ['3'] },
169 169 '=3' => { :op => '=', :values => ['3'] }},
170 170 'start_date' => {
171 171 '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
172 172 '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
173 173 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
174 174 '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
175 175 '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
176 176 '<t+2' => { :op => '<t+', :values => ['2'] },
177 177 '>t+2' => { :op => '>t+', :values => ['2'] },
178 178 't+2' => { :op => 't+', :values => ['2'] },
179 179 't' => { :op => 't', :values => [''] },
180 180 'w' => { :op => 'w', :values => [''] },
181 181 '>t-2' => { :op => '>t-', :values => ['2'] },
182 182 '<t-2' => { :op => '<t-', :values => ['2'] },
183 183 't-2' => { :op => 't-', :values => ['2'] }},
184 184 'created_on' => {
185 185 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
186 186 '<t+2' => { :op => '=', :values => ['<t+2'] },
187 187 '>t+2' => { :op => '=', :values => ['>t+2'] },
188 188 't+2' => { :op => 't', :values => ['+2'] }},
189 189 'cf_1' => {
190 190 'c' => { :op => '=', :values => ['c'] },
191 191 '!c' => { :op => '!', :values => ['c'] },
192 192 '!*' => { :op => '!*', :values => [''] },
193 193 '*' => { :op => '*', :values => [''] }},
194 194 'estimated_hours' => {
195 195 '=13.4' => { :op => '=', :values => ['13.4'] },
196 196 '>=45' => { :op => '>=', :values => ['45'] },
197 197 '<=125' => { :op => '<=', :values => ['125'] },
198 198 '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
199 199 '!*' => { :op => '!*', :values => [''] },
200 200 '*' => { :op => '*', :values => [''] }}
201 201 }
202 202
203 203 default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
204 204
205 205 to_test.each do |field, expression_and_expected|
206 206 expression_and_expected.each do |filter_expression, expected|
207 207
208 208 get :index, :set_filter => 1, field => filter_expression
209 209
210 210 assert_response :success
211 211 assert_template 'index'
212 212 assert_not_nil assigns(:issues)
213 213
214 214 query = assigns(:query)
215 215 assert_not_nil query
216 216 assert query.has_filter?(field)
217 217 assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
218 218 end
219 219 end
220 220
221 221 end
222 222
223 223 def test_index_with_project_and_empty_filters
224 224 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
225 225 assert_response :success
226 226 assert_template 'index'
227 227 assert_not_nil assigns(:issues)
228 228
229 229 query = assigns(:query)
230 230 assert_not_nil query
231 231 # no filter
232 232 assert_equal({}, query.filters)
233 233 end
234 234
235 235 def test_index_with_query
236 236 get :index, :project_id => 1, :query_id => 5
237 237 assert_response :success
238 238 assert_template 'index'
239 239 assert_not_nil assigns(:issues)
240 240 assert_nil assigns(:issue_count_by_group)
241 241 end
242 242
243 243 def test_index_with_query_grouped_by_tracker
244 244 get :index, :project_id => 1, :query_id => 6
245 245 assert_response :success
246 246 assert_template 'index'
247 247 assert_not_nil assigns(:issues)
248 248 assert_not_nil assigns(:issue_count_by_group)
249 249 end
250 250
251 251 def test_index_with_query_grouped_by_list_custom_field
252 252 get :index, :project_id => 1, :query_id => 9
253 253 assert_response :success
254 254 assert_template 'index'
255 255 assert_not_nil assigns(:issues)
256 256 assert_not_nil assigns(:issue_count_by_group)
257 257 end
258 258
259 259 def test_index_with_query_id_and_project_id_should_set_session_query
260 260 get :index, :project_id => 1, :query_id => 4
261 261 assert_response :success
262 262 assert_kind_of Hash, session[:query]
263 263 assert_equal 4, session[:query][:id]
264 264 assert_equal 1, session[:query][:project_id]
265 265 end
266 266
267 267 def test_index_with_cross_project_query_in_session_should_show_project_issues
268 268 q = Query.create!(:name => "test", :user_id => 2, :is_public => false, :project => nil)
269 269 @request.session[:query] = {:id => q.id, :project_id => 1}
270 270
271 271 with_settings :display_subprojects_issues => '0' do
272 272 get :index, :project_id => 1
273 273 end
274 274 assert_response :success
275 275 assert_not_nil assigns(:query)
276 276 assert_equal q.id, assigns(:query).id
277 277 assert_equal 1, assigns(:query).project_id
278 278 assert_equal [1], assigns(:issues).map(&:project_id).uniq
279 279 end
280 280
281 281 def test_private_query_should_not_be_available_to_other_users
282 282 q = Query.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil)
283 283 @request.session[:user_id] = 3
284 284
285 285 get :index, :query_id => q.id
286 286 assert_response 403
287 287 end
288 288
289 289 def test_private_query_should_be_available_to_its_user
290 290 q = Query.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil)
291 291 @request.session[:user_id] = 2
292 292
293 293 get :index, :query_id => q.id
294 294 assert_response :success
295 295 end
296 296
297 297 def test_public_query_should_be_available_to_other_users
298 298 q = Query.create!(:name => "private", :user => User.find(2), :is_public => true, :project => nil)
299 299 @request.session[:user_id] = 3
300 300
301 301 get :index, :query_id => q.id
302 302 assert_response :success
303 303 end
304 304
305 305 def test_index_csv
306 306 get :index, :format => 'csv'
307 307 assert_response :success
308 308 assert_not_nil assigns(:issues)
309 309 assert_equal 'text/csv', @response.content_type
310 310 assert @response.body.starts_with?("#,")
311 311 lines = @response.body.chomp.split("\n")
312 312 assert_equal assigns(:query).columns.size + 1, lines[0].split(',').size
313 313 end
314 314
315 315 def test_index_csv_with_project
316 316 get :index, :project_id => 1, :format => 'csv'
317 317 assert_response :success
318 318 assert_not_nil assigns(:issues)
319 319 assert_equal 'text/csv', @response.content_type
320 320 end
321 321
322 322 def test_index_csv_with_description
323 323 get :index, :format => 'csv', :description => '1'
324 324 assert_response :success
325 325 assert_not_nil assigns(:issues)
326 326 assert_equal 'text/csv', @response.content_type
327 327 assert @response.body.starts_with?("#,")
328 328 lines = @response.body.chomp.split("\n")
329 329 assert_equal assigns(:query).columns.size + 2, lines[0].split(',').size
330 330 end
331 331
332 def test_index_csv_with_spent_time_column
333 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column')
334 TimeEntry.generate!(:project_id => issue.project_id, :issue_id => issue.id, :hours => 7.33)
335
336 get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
337 assert_response :success
338 assert_equal 'text/csv', @response.content_type
339 lines = @response.body.chomp.split("\n")
340 assert_include "#{issue.id},#{issue.subject},7.33", lines
341 end
342
332 343 def test_index_csv_with_all_columns
333 344 get :index, :format => 'csv', :columns => 'all'
334 345 assert_response :success
335 346 assert_not_nil assigns(:issues)
336 347 assert_equal 'text/csv', @response.content_type
337 348 assert @response.body.starts_with?("#,")
338 349 lines = @response.body.chomp.split("\n")
339 350 assert_equal assigns(:query).available_columns.size + 1, lines[0].split(',').size
340 351 end
341 352
342 353 def test_index_csv_with_multi_column_field
343 354 CustomField.find(1).update_attribute :multiple, true
344 355 issue = Issue.find(1)
345 356 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
346 357 issue.save!
347 358
348 359 get :index, :format => 'csv', :columns => 'all'
349 360 assert_response :success
350 361 lines = @response.body.chomp.split("\n")
351 362 assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
352 363 end
353 364
354 365 def test_index_csv_big_5
355 366 with_settings :default_language => "zh-TW" do
356 367 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
357 368 str_big5 = "\xa4@\xa4\xeb"
358 369 if str_utf8.respond_to?(:force_encoding)
359 370 str_utf8.force_encoding('UTF-8')
360 371 str_big5.force_encoding('Big5')
361 372 end
362 373 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
363 374 :status_id => 1, :priority => IssuePriority.all.first,
364 375 :subject => str_utf8)
365 376 assert issue.save
366 377
367 378 get :index, :project_id => 1,
368 379 :f => ['subject'],
369 380 :op => '=', :values => [str_utf8],
370 381 :format => 'csv'
371 382 assert_equal 'text/csv', @response.content_type
372 383 lines = @response.body.chomp.split("\n")
373 384 s1 = "\xaa\xac\xbaA"
374 385 if str_utf8.respond_to?(:force_encoding)
375 386 s1.force_encoding('Big5')
376 387 end
377 388 assert lines[0].include?(s1)
378 389 assert lines[1].include?(str_big5)
379 390 end
380 391 end
381 392
382 393 def test_index_csv_cannot_convert_should_be_replaced_big_5
383 394 with_settings :default_language => "zh-TW" do
384 395 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
385 396 if str_utf8.respond_to?(:force_encoding)
386 397 str_utf8.force_encoding('UTF-8')
387 398 end
388 399 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
389 400 :status_id => 1, :priority => IssuePriority.all.first,
390 401 :subject => str_utf8)
391 402 assert issue.save
392 403
393 404 get :index, :project_id => 1,
394 405 :f => ['subject'],
395 406 :op => '=', :values => [str_utf8],
396 407 :c => ['status', 'subject'],
397 408 :format => 'csv',
398 409 :set_filter => 1
399 410 assert_equal 'text/csv', @response.content_type
400 411 lines = @response.body.chomp.split("\n")
401 412 s1 = "\xaa\xac\xbaA" # status
402 413 if str_utf8.respond_to?(:force_encoding)
403 414 s1.force_encoding('Big5')
404 415 end
405 416 assert lines[0].include?(s1)
406 417 s2 = lines[1].split(",")[2]
407 418 if s1.respond_to?(:force_encoding)
408 419 s3 = "\xa5H?" # subject
409 420 s3.force_encoding('Big5')
410 421 assert_equal s3, s2
411 422 elsif RUBY_PLATFORM == 'java'
412 423 assert_equal "??", s2
413 424 else
414 425 assert_equal "\xa5H???", s2
415 426 end
416 427 end
417 428 end
418 429
419 430 def test_index_csv_tw
420 431 with_settings :default_language => "zh-TW" do
421 432 str1 = "test_index_csv_tw"
422 433 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
423 434 :status_id => 1, :priority => IssuePriority.all.first,
424 435 :subject => str1, :estimated_hours => '1234.5')
425 436 assert issue.save
426 437 assert_equal 1234.5, issue.estimated_hours
427 438
428 439 get :index, :project_id => 1,
429 440 :f => ['subject'],
430 441 :op => '=', :values => [str1],
431 442 :c => ['estimated_hours', 'subject'],
432 443 :format => 'csv',
433 444 :set_filter => 1
434 445 assert_equal 'text/csv', @response.content_type
435 446 lines = @response.body.chomp.split("\n")
436 assert_equal "#{issue.id},1234.5,#{str1}", lines[1]
447 assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
437 448
438 449 str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
439 450 if str_tw.respond_to?(:force_encoding)
440 451 str_tw.force_encoding('UTF-8')
441 452 end
442 453 assert_equal str_tw, l(:general_lang_name)
443 454 assert_equal ',', l(:general_csv_separator)
444 455 assert_equal '.', l(:general_csv_decimal_separator)
445 456 end
446 457 end
447 458
448 459 def test_index_csv_fr
449 460 with_settings :default_language => "fr" do
450 461 str1 = "test_index_csv_fr"
451 462 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
452 463 :status_id => 1, :priority => IssuePriority.all.first,
453 464 :subject => str1, :estimated_hours => '1234.5')
454 465 assert issue.save
455 466 assert_equal 1234.5, issue.estimated_hours
456 467
457 468 get :index, :project_id => 1,
458 469 :f => ['subject'],
459 470 :op => '=', :values => [str1],
460 471 :c => ['estimated_hours', 'subject'],
461 472 :format => 'csv',
462 473 :set_filter => 1
463 474 assert_equal 'text/csv', @response.content_type
464 475 lines = @response.body.chomp.split("\n")
465 assert_equal "#{issue.id};1234,5;#{str1}", lines[1]
476 assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
466 477
467 478 str_fr = "Fran\xc3\xa7ais"
468 479 if str_fr.respond_to?(:force_encoding)
469 480 str_fr.force_encoding('UTF-8')
470 481 end
471 482 assert_equal str_fr, l(:general_lang_name)
472 483 assert_equal ';', l(:general_csv_separator)
473 484 assert_equal ',', l(:general_csv_decimal_separator)
474 485 end
475 486 end
476 487
477 488 def test_index_pdf
478 489 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
479 490 with_settings :default_language => lang do
480 491
481 492 get :index
482 493 assert_response :success
483 494 assert_template 'index'
484 495
485 496 if lang == "ja"
486 497 if RUBY_PLATFORM != 'java'
487 498 assert_equal "CP932", l(:general_pdf_encoding)
488 499 end
489 500 if RUBY_PLATFORM == 'java' && l(:general_pdf_encoding) == "CP932"
490 501 next
491 502 end
492 503 end
493 504
494 505 get :index, :format => 'pdf'
495 506 assert_response :success
496 507 assert_not_nil assigns(:issues)
497 508 assert_equal 'application/pdf', @response.content_type
498 509
499 510 get :index, :project_id => 1, :format => 'pdf'
500 511 assert_response :success
501 512 assert_not_nil assigns(:issues)
502 513 assert_equal 'application/pdf', @response.content_type
503 514
504 515 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
505 516 assert_response :success
506 517 assert_not_nil assigns(:issues)
507 518 assert_equal 'application/pdf', @response.content_type
508 519 end
509 520 end
510 521 end
511 522
512 523 def test_index_pdf_with_query_grouped_by_list_custom_field
513 524 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
514 525 assert_response :success
515 526 assert_not_nil assigns(:issues)
516 527 assert_not_nil assigns(:issue_count_by_group)
517 528 assert_equal 'application/pdf', @response.content_type
518 529 end
519 530
520 531 def test_index_sort
521 532 get :index, :sort => 'tracker,id:desc'
522 533 assert_response :success
523 534
524 535 sort_params = @request.session['issues_index_sort']
525 536 assert sort_params.is_a?(String)
526 537 assert_equal 'tracker,id:desc', sort_params
527 538
528 539 issues = assigns(:issues)
529 540 assert_not_nil issues
530 541 assert !issues.empty?
531 542 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
532 543 end
533 544
534 545 def test_index_sort_by_field_not_included_in_columns
535 546 Setting.issue_list_default_columns = %w(subject author)
536 547 get :index, :sort => 'tracker'
537 548 end
538 549
539 550 def test_index_sort_by_assigned_to
540 551 get :index, :sort => 'assigned_to'
541 552 assert_response :success
542 553 assignees = assigns(:issues).collect(&:assigned_to).compact
543 554 assert_equal assignees.sort, assignees
544 555 end
545 556
546 557 def test_index_sort_by_assigned_to_desc
547 558 get :index, :sort => 'assigned_to:desc'
548 559 assert_response :success
549 560 assignees = assigns(:issues).collect(&:assigned_to).compact
550 561 assert_equal assignees.sort.reverse, assignees
551 562 end
552 563
553 564 def test_index_group_by_assigned_to
554 565 get :index, :group_by => 'assigned_to', :sort => 'priority'
555 566 assert_response :success
556 567 end
557 568
558 569 def test_index_sort_by_author
559 570 get :index, :sort => 'author'
560 571 assert_response :success
561 572 authors = assigns(:issues).collect(&:author)
562 573 assert_equal authors.sort, authors
563 574 end
564 575
565 576 def test_index_sort_by_author_desc
566 577 get :index, :sort => 'author:desc'
567 578 assert_response :success
568 579 authors = assigns(:issues).collect(&:author)
569 580 assert_equal authors.sort.reverse, authors
570 581 end
571 582
572 583 def test_index_group_by_author
573 584 get :index, :group_by => 'author', :sort => 'priority'
574 585 assert_response :success
575 586 end
576 587
577 588 def test_index_sort_by_spent_hours
578 589 get :index, :sort => 'spent_hours:desc'
579 590 assert_response :success
580 591 hours = assigns(:issues).collect(&:spent_hours)
581 592 assert_equal hours.sort.reverse, hours
582 593 end
583 594
584 595 def test_index_with_columns
585 596 columns = ['tracker', 'subject', 'assigned_to']
586 597 get :index, :set_filter => 1, :c => columns
587 598 assert_response :success
588 599
589 600 # query should use specified columns
590 601 query = assigns(:query)
591 602 assert_kind_of Query, query
592 603 assert_equal columns, query.column_names.map(&:to_s)
593 604
594 605 # columns should be stored in session
595 606 assert_kind_of Hash, session[:query]
596 607 assert_kind_of Array, session[:query][:column_names]
597 608 assert_equal columns, session[:query][:column_names].map(&:to_s)
598 609
599 610 # ensure only these columns are kept in the selected columns list
600 611 assert_tag :tag => 'select', :attributes => { :id => 'selected_columns' },
601 612 :children => { :count => 3 }
602 613 assert_no_tag :tag => 'option', :attributes => { :value => 'project' },
603 614 :parent => { :tag => 'select', :attributes => { :id => "selected_columns" } }
604 615 end
605 616
606 617 def test_index_without_project_should_implicitly_add_project_column_to_default_columns
607 618 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
608 619 get :index, :set_filter => 1
609 620
610 621 # query should use specified columns
611 622 query = assigns(:query)
612 623 assert_kind_of Query, query
613 624 assert_equal [:project, :tracker, :subject, :assigned_to], query.columns.map(&:name)
614 625 end
615 626
616 627 def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
617 628 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
618 629 columns = ['tracker', 'subject', 'assigned_to']
619 630 get :index, :set_filter => 1, :c => columns
620 631
621 632 # query should use specified columns
622 633 query = assigns(:query)
623 634 assert_kind_of Query, query
624 635 assert_equal columns.map(&:to_sym), query.columns.map(&:name)
625 636 end
626 637
627 638 def test_index_with_custom_field_column
628 639 columns = %w(tracker subject cf_2)
629 640 get :index, :set_filter => 1, :c => columns
630 641 assert_response :success
631 642
632 643 # query should use specified columns
633 644 query = assigns(:query)
634 645 assert_kind_of Query, query
635 646 assert_equal columns, query.column_names.map(&:to_s)
636 647
637 648 assert_tag :td,
638 649 :attributes => {:class => 'cf_2 string'},
639 650 :ancestor => {:tag => 'table', :attributes => {:class => /issues/}}
640 651 end
641 652
642 653 def test_index_with_multi_custom_field_column
643 654 field = CustomField.find(1)
644 655 field.update_attribute :multiple, true
645 656 issue = Issue.find(1)
646 657 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
647 658 issue.save!
648 659
649 660 get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
650 661 assert_response :success
651 662
652 663 assert_tag :td,
653 664 :attributes => {:class => /cf_1/},
654 665 :content => 'MySQL, Oracle'
655 666 end
656 667
657 668 def test_index_with_multi_user_custom_field_column
658 669 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
659 670 :tracker_ids => [1], :is_for_all => true)
660 671 issue = Issue.find(1)
661 672 issue.custom_field_values = {field.id => ['2', '3']}
662 673 issue.save!
663 674
664 675 get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
665 676 assert_response :success
666 677
667 678 assert_tag :td,
668 679 :attributes => {:class => /cf_#{field.id}/},
669 680 :child => {:tag => 'a', :content => 'John Smith'}
670 681 end
671 682
672 683 def test_index_with_date_column
673 684 Issue.find(1).update_attribute :start_date, '1987-08-24'
674 685
675 686 with_settings :date_format => '%d/%m/%Y' do
676 687 get :index, :set_filter => 1, :c => %w(start_date)
677 688 assert_tag 'td', :attributes => {:class => /start_date/}, :content => '24/08/1987'
678 689 end
679 690 end
680 691
681 692 def test_index_with_done_ratio
682 693 Issue.find(1).update_attribute :done_ratio, 40
683 694
684 695 get :index, :set_filter => 1, :c => %w(done_ratio)
685 696 assert_tag 'td', :attributes => {:class => /done_ratio/},
686 697 :child => {:tag => 'table', :attributes => {:class => 'progress'},
687 698 :descendant => {:tag => 'td', :attributes => {:class => 'closed', :style => 'width: 40%;'}}
688 699 }
689 700 end
690 701
691 702 def test_index_with_spent_hours_column
692 703 get :index, :set_filter => 1, :c => %w(subject spent_hours)
693 704
694 705 assert_tag 'tr', :attributes => {:id => 'issue-3'},
695 706 :child => {
696 707 :tag => 'td', :attributes => {:class => /spent_hours/}, :content => '1.00'
697 708 }
698 709 end
699 710
700 711 def test_index_should_not_show_spent_hours_column_without_permission
701 712 Role.anonymous.remove_permission! :view_time_entries
702 713 get :index, :set_filter => 1, :c => %w(subject spent_hours)
703 714
704 715 assert_no_tag 'td', :attributes => {:class => /spent_hours/}
705 716 end
706 717
707 718 def test_index_with_fixed_version
708 719 get :index, :set_filter => 1, :c => %w(fixed_version)
709 720 assert_tag 'td', :attributes => {:class => /fixed_version/},
710 721 :child => {:tag => 'a', :content => '1.0', :attributes => {:href => '/versions/2'}}
711 722 end
712 723
713 724 def test_index_send_html_if_query_is_invalid
714 725 get :index, :f => ['start_date'], :op => {:start_date => '='}
715 726 assert_equal 'text/html', @response.content_type
716 727 assert_template 'index'
717 728 end
718 729
719 730 def test_index_send_nothing_if_query_is_invalid
720 731 get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
721 732 assert_equal 'text/csv', @response.content_type
722 733 assert @response.body.blank?
723 734 end
724 735
725 736 def test_show_by_anonymous
726 737 get :show, :id => 1
727 738 assert_response :success
728 739 assert_template 'show'
729 740 assert_not_nil assigns(:issue)
730 741 assert_equal Issue.find(1), assigns(:issue)
731 742
732 743 # anonymous role is allowed to add a note
733 744 assert_tag :tag => 'form',
734 745 :descendant => { :tag => 'fieldset',
735 746 :child => { :tag => 'legend',
736 747 :content => /Notes/ } }
737 748 assert_tag :tag => 'title',
738 749 :content => "Bug #1: Can't print recipes - eCookbook - Redmine"
739 750 end
740 751
741 752 def test_show_by_manager
742 753 @request.session[:user_id] = 2
743 754 get :show, :id => 1
744 755 assert_response :success
745 756
746 757 assert_tag :tag => 'a',
747 758 :content => /Quote/
748 759
749 760 assert_tag :tag => 'form',
750 761 :descendant => { :tag => 'fieldset',
751 762 :child => { :tag => 'legend',
752 763 :content => /Change properties/ } },
753 764 :descendant => { :tag => 'fieldset',
754 765 :child => { :tag => 'legend',
755 766 :content => /Log time/ } },
756 767 :descendant => { :tag => 'fieldset',
757 768 :child => { :tag => 'legend',
758 769 :content => /Notes/ } }
759 770 end
760 771
761 772 def test_show_should_display_update_form
762 773 @request.session[:user_id] = 2
763 774 get :show, :id => 1
764 775 assert_response :success
765 776
766 777 assert_tag 'form', :attributes => {:id => 'issue-form'}
767 778 assert_tag 'input', :attributes => {:name => 'issue[is_private]'}
768 779 assert_tag 'select', :attributes => {:name => 'issue[project_id]'}
769 780 assert_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
770 781 assert_tag 'input', :attributes => {:name => 'issue[subject]'}
771 782 assert_tag 'textarea', :attributes => {:name => 'issue[description]'}
772 783 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
773 784 assert_tag 'select', :attributes => {:name => 'issue[priority_id]'}
774 785 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
775 786 assert_tag 'select', :attributes => {:name => 'issue[category_id]'}
776 787 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
777 788 assert_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
778 789 assert_tag 'input', :attributes => {:name => 'issue[start_date]'}
779 790 assert_tag 'input', :attributes => {:name => 'issue[due_date]'}
780 791 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
781 792 assert_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]' }
782 793 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
783 794 assert_tag 'textarea', :attributes => {:name => 'notes'}
784 795 end
785 796
786 797 def test_show_should_display_update_form_with_minimal_permissions
787 798 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
788 799 Workflow.delete_all :role_id => 1
789 800
790 801 @request.session[:user_id] = 2
791 802 get :show, :id => 1
792 803 assert_response :success
793 804
794 805 assert_tag 'form', :attributes => {:id => 'issue-form'}
795 806 assert_no_tag 'input', :attributes => {:name => 'issue[is_private]'}
796 807 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
797 808 assert_no_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
798 809 assert_no_tag 'input', :attributes => {:name => 'issue[subject]'}
799 810 assert_no_tag 'textarea', :attributes => {:name => 'issue[description]'}
800 811 assert_no_tag 'select', :attributes => {:name => 'issue[status_id]'}
801 812 assert_no_tag 'select', :attributes => {:name => 'issue[priority_id]'}
802 813 assert_no_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
803 814 assert_no_tag 'select', :attributes => {:name => 'issue[category_id]'}
804 815 assert_no_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
805 816 assert_no_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
806 817 assert_no_tag 'input', :attributes => {:name => 'issue[start_date]'}
807 818 assert_no_tag 'input', :attributes => {:name => 'issue[due_date]'}
808 819 assert_no_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
809 820 assert_no_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]' }
810 821 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
811 822 assert_tag 'textarea', :attributes => {:name => 'notes'}
812 823 end
813 824
814 825 def test_show_should_display_update_form_with_workflow_permissions
815 826 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
816 827
817 828 @request.session[:user_id] = 2
818 829 get :show, :id => 1
819 830 assert_response :success
820 831
821 832 assert_tag 'form', :attributes => {:id => 'issue-form'}
822 833 assert_no_tag 'input', :attributes => {:name => 'issue[is_private]'}
823 834 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
824 835 assert_no_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
825 836 assert_no_tag 'input', :attributes => {:name => 'issue[subject]'}
826 837 assert_no_tag 'textarea', :attributes => {:name => 'issue[description]'}
827 838 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
828 839 assert_no_tag 'select', :attributes => {:name => 'issue[priority_id]'}
829 840 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
830 841 assert_no_tag 'select', :attributes => {:name => 'issue[category_id]'}
831 842 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
832 843 assert_no_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
833 844 assert_no_tag 'input', :attributes => {:name => 'issue[start_date]'}
834 845 assert_no_tag 'input', :attributes => {:name => 'issue[due_date]'}
835 846 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
836 847 assert_no_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]' }
837 848 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
838 849 assert_tag 'textarea', :attributes => {:name => 'notes'}
839 850 end
840 851
841 852 def test_show_should_not_display_update_form_without_permissions
842 853 Role.find(1).update_attribute :permissions, [:view_issues]
843 854
844 855 @request.session[:user_id] = 2
845 856 get :show, :id => 1
846 857 assert_response :success
847 858
848 859 assert_no_tag 'form', :attributes => {:id => 'issue-form'}
849 860 end
850 861
851 862 def test_update_form_should_not_display_inactive_enumerations
852 863 @request.session[:user_id] = 2
853 864 get :show, :id => 1
854 865 assert_response :success
855 866
856 867 assert ! IssuePriority.find(15).active?
857 868 assert_no_tag :option, :attributes => {:value => '15'},
858 869 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
859 870 end
860 871
861 872 def test_update_form_should_allow_attachment_upload
862 873 @request.session[:user_id] = 2
863 874 get :show, :id => 1
864 875
865 876 assert_tag :tag => 'form',
866 877 :attributes => {:id => 'issue-form', :method => 'post', :enctype => 'multipart/form-data'},
867 878 :descendant => {
868 879 :tag => 'input',
869 880 :attributes => {:type => 'file', :name => 'attachments[1][file]'}
870 881 }
871 882 end
872 883
873 884 def test_show_should_deny_anonymous_access_without_permission
874 885 Role.anonymous.remove_permission!(:view_issues)
875 886 get :show, :id => 1
876 887 assert_response :redirect
877 888 end
878 889
879 890 def test_show_should_deny_anonymous_access_to_private_issue
880 891 Issue.update_all(["is_private = ?", true], "id = 1")
881 892 get :show, :id => 1
882 893 assert_response :redirect
883 894 end
884 895
885 896 def test_show_should_deny_non_member_access_without_permission
886 897 Role.non_member.remove_permission!(:view_issues)
887 898 @request.session[:user_id] = 9
888 899 get :show, :id => 1
889 900 assert_response 403
890 901 end
891 902
892 903 def test_show_should_deny_non_member_access_to_private_issue
893 904 Issue.update_all(["is_private = ?", true], "id = 1")
894 905 @request.session[:user_id] = 9
895 906 get :show, :id => 1
896 907 assert_response 403
897 908 end
898 909
899 910 def test_show_should_deny_member_access_without_permission
900 911 Role.find(1).remove_permission!(:view_issues)
901 912 @request.session[:user_id] = 2
902 913 get :show, :id => 1
903 914 assert_response 403
904 915 end
905 916
906 917 def test_show_should_deny_member_access_to_private_issue_without_permission
907 918 Issue.update_all(["is_private = ?", true], "id = 1")
908 919 @request.session[:user_id] = 3
909 920 get :show, :id => 1
910 921 assert_response 403
911 922 end
912 923
913 924 def test_show_should_allow_author_access_to_private_issue
914 925 Issue.update_all(["is_private = ?, author_id = 3", true], "id = 1")
915 926 @request.session[:user_id] = 3
916 927 get :show, :id => 1
917 928 assert_response :success
918 929 end
919 930
920 931 def test_show_should_allow_assignee_access_to_private_issue
921 932 Issue.update_all(["is_private = ?, assigned_to_id = 3", true], "id = 1")
922 933 @request.session[:user_id] = 3
923 934 get :show, :id => 1
924 935 assert_response :success
925 936 end
926 937
927 938 def test_show_should_allow_member_access_to_private_issue_with_permission
928 939 Issue.update_all(["is_private = ?", true], "id = 1")
929 940 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
930 941 @request.session[:user_id] = 3
931 942 get :show, :id => 1
932 943 assert_response :success
933 944 end
934 945
935 946 def test_show_should_not_disclose_relations_to_invisible_issues
936 947 Setting.cross_project_issue_relations = '1'
937 948 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
938 949 # Relation to a private project issue
939 950 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
940 951
941 952 get :show, :id => 1
942 953 assert_response :success
943 954
944 955 assert_tag :div, :attributes => { :id => 'relations' },
945 956 :descendant => { :tag => 'a', :content => /#2$/ }
946 957 assert_no_tag :div, :attributes => { :id => 'relations' },
947 958 :descendant => { :tag => 'a', :content => /#4$/ }
948 959 end
949 960
950 961 def test_show_should_list_subtasks
951 962 Issue.generate!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
952 963
953 964 get :show, :id => 1
954 965 assert_response :success
955 966 assert_tag 'div', :attributes => {:id => 'issue_tree'},
956 967 :descendant => {:tag => 'td', :content => /Child Issue/, :attributes => {:class => /subject/}}
957 968 end
958 969
959 970 def test_show_should_list_parents
960 971 issue = Issue.generate!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
961 972
962 973 get :show, :id => issue.id
963 974 assert_response :success
964 975 assert_tag 'div', :attributes => {:class => 'subject'},
965 976 :descendant => {:tag => 'h3', :content => 'Child Issue'}
966 977 assert_tag 'div', :attributes => {:class => 'subject'},
967 978 :descendant => {:tag => 'a', :attributes => {:href => '/issues/1'}}
968 979 end
969 980
970 981 def test_show_should_not_display_prev_next_links_without_query_in_session
971 982 get :show, :id => 1
972 983 assert_response :success
973 984 assert_nil assigns(:prev_issue_id)
974 985 assert_nil assigns(:next_issue_id)
975 986
976 987 assert_no_tag 'div', :attributes => {:class => /next-prev-links/}
977 988 end
978 989
979 990 def test_show_should_display_prev_next_links_with_query_in_session
980 991 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
981 992 @request.session['issues_index_sort'] = 'id'
982 993
983 994 with_settings :display_subprojects_issues => '0' do
984 995 get :show, :id => 3
985 996 end
986 997
987 998 assert_response :success
988 999 # Previous and next issues for all projects
989 1000 assert_equal 2, assigns(:prev_issue_id)
990 1001 assert_equal 5, assigns(:next_issue_id)
991 1002
992 1003 assert_tag 'div', :attributes => {:class => /next-prev-links/}
993 1004 assert_tag 'a', :attributes => {:href => '/issues/2'}, :content => /Previous/
994 1005 assert_tag 'a', :attributes => {:href => '/issues/5'}, :content => /Next/
995 1006
996 1007 count = Issue.open.visible.count
997 1008 assert_tag 'span', :attributes => {:class => 'position'}, :content => "3 of #{count}"
998 1009 end
999 1010
1000 1011 def test_show_should_display_prev_next_links_with_saved_query_in_session
1001 1012 query = Query.create!(:name => 'test', :is_public => true, :user_id => 1,
1002 1013 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1003 1014 :sort_criteria => [['id', 'asc']])
1004 1015 @request.session[:query] = {:id => query.id, :project_id => nil}
1005 1016
1006 1017 get :show, :id => 11
1007 1018
1008 1019 assert_response :success
1009 1020 assert_equal query, assigns(:query)
1010 1021 # Previous and next issues for all projects
1011 1022 assert_equal 8, assigns(:prev_issue_id)
1012 1023 assert_equal 12, assigns(:next_issue_id)
1013 1024
1014 1025 assert_tag 'a', :attributes => {:href => '/issues/8'}, :content => /Previous/
1015 1026 assert_tag 'a', :attributes => {:href => '/issues/12'}, :content => /Next/
1016 1027 end
1017 1028
1018 1029 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1019 1030 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1020 1031
1021 1032 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1022 1033 @request.session['issues_index_sort'] = assoc_sort
1023 1034
1024 1035 get :show, :id => 3
1025 1036 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1026 1037
1027 1038 assert_tag 'a', :content => /Previous/
1028 1039 assert_tag 'a', :content => /Next/
1029 1040 end
1030 1041 end
1031 1042
1032 1043 def test_show_should_display_prev_next_links_with_project_query_in_session
1033 1044 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1034 1045 @request.session['issues_index_sort'] = 'id'
1035 1046
1036 1047 with_settings :display_subprojects_issues => '0' do
1037 1048 get :show, :id => 3
1038 1049 end
1039 1050
1040 1051 assert_response :success
1041 1052 # Previous and next issues inside project
1042 1053 assert_equal 2, assigns(:prev_issue_id)
1043 1054 assert_equal 7, assigns(:next_issue_id)
1044 1055
1045 1056 assert_tag 'a', :attributes => {:href => '/issues/2'}, :content => /Previous/
1046 1057 assert_tag 'a', :attributes => {:href => '/issues/7'}, :content => /Next/
1047 1058 end
1048 1059
1049 1060 def test_show_should_not_display_prev_link_for_first_issue
1050 1061 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1051 1062 @request.session['issues_index_sort'] = 'id'
1052 1063
1053 1064 with_settings :display_subprojects_issues => '0' do
1054 1065 get :show, :id => 1
1055 1066 end
1056 1067
1057 1068 assert_response :success
1058 1069 assert_nil assigns(:prev_issue_id)
1059 1070 assert_equal 2, assigns(:next_issue_id)
1060 1071
1061 1072 assert_no_tag 'a', :content => /Previous/
1062 1073 assert_tag 'a', :attributes => {:href => '/issues/2'}, :content => /Next/
1063 1074 end
1064 1075
1065 1076 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1066 1077 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1067 1078 @request.session['issues_index_sort'] = 'id'
1068 1079
1069 1080 get :show, :id => 1
1070 1081
1071 1082 assert_response :success
1072 1083 assert_nil assigns(:prev_issue_id)
1073 1084 assert_nil assigns(:next_issue_id)
1074 1085
1075 1086 assert_no_tag 'a', :content => /Previous/
1076 1087 assert_no_tag 'a', :content => /Next/
1077 1088 end
1078 1089
1079 1090 def test_show_should_display_visible_changesets_from_other_projects
1080 1091 project = Project.find(2)
1081 1092 issue = project.issues.first
1082 1093 issue.changeset_ids = [102]
1083 1094 issue.save!
1084 1095 project.disable_module! :repository
1085 1096
1086 1097 @request.session[:user_id] = 2
1087 1098 get :show, :id => issue.id
1088 1099 assert_tag 'a', :attributes => {:href => "/projects/ecookbook/repository/revisions/3"}
1089 1100 end
1090 1101
1091 1102 def test_show_with_multi_custom_field
1092 1103 field = CustomField.find(1)
1093 1104 field.update_attribute :multiple, true
1094 1105 issue = Issue.find(1)
1095 1106 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1096 1107 issue.save!
1097 1108
1098 1109 get :show, :id => 1
1099 1110 assert_response :success
1100 1111
1101 1112 assert_tag :td, :content => 'MySQL, Oracle'
1102 1113 end
1103 1114
1104 1115 def test_show_with_multi_user_custom_field
1105 1116 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1106 1117 :tracker_ids => [1], :is_for_all => true)
1107 1118 issue = Issue.find(1)
1108 1119 issue.custom_field_values = {field.id => ['2', '3']}
1109 1120 issue.save!
1110 1121
1111 1122 get :show, :id => 1
1112 1123 assert_response :success
1113 1124
1114 1125 # TODO: should display links
1115 1126 assert_tag :td, :content => 'Dave Lopper, John Smith'
1116 1127 end
1117 1128
1118 1129 def test_show_atom
1119 1130 get :show, :id => 2, :format => 'atom'
1120 1131 assert_response :success
1121 1132 assert_template 'journals/index'
1122 1133 # Inline image
1123 1134 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1124 1135 end
1125 1136
1126 1137 def test_show_export_to_pdf
1127 1138 get :show, :id => 3, :format => 'pdf'
1128 1139 assert_response :success
1129 1140 assert_equal 'application/pdf', @response.content_type
1130 1141 assert @response.body.starts_with?('%PDF')
1131 1142 assert_not_nil assigns(:issue)
1132 1143 end
1133 1144
1134 1145 def test_get_new
1135 1146 @request.session[:user_id] = 2
1136 1147 get :new, :project_id => 1, :tracker_id => 1
1137 1148 assert_response :success
1138 1149 assert_template 'new'
1139 1150
1140 1151 assert_tag 'input', :attributes => {:name => 'issue[is_private]'}
1141 1152 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
1142 1153 assert_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
1143 1154 assert_tag 'input', :attributes => {:name => 'issue[subject]'}
1144 1155 assert_tag 'textarea', :attributes => {:name => 'issue[description]'}
1145 1156 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
1146 1157 assert_tag 'select', :attributes => {:name => 'issue[priority_id]'}
1147 1158 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
1148 1159 assert_tag 'select', :attributes => {:name => 'issue[category_id]'}
1149 1160 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
1150 1161 assert_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
1151 1162 assert_tag 'input', :attributes => {:name => 'issue[start_date]'}
1152 1163 assert_tag 'input', :attributes => {:name => 'issue[due_date]'}
1153 1164 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
1154 1165 assert_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]', :value => 'Default string' }
1155 1166 assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
1156 1167
1157 1168 # Be sure we don't display inactive IssuePriorities
1158 1169 assert ! IssuePriority.find(15).active?
1159 1170 assert_no_tag :option, :attributes => {:value => '15'},
1160 1171 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
1161 1172 end
1162 1173
1163 1174 def test_get_new_with_minimal_permissions
1164 1175 Role.find(1).update_attribute :permissions, [:add_issues]
1165 1176 Workflow.delete_all :role_id => 1
1166 1177
1167 1178 @request.session[:user_id] = 2
1168 1179 get :new, :project_id => 1, :tracker_id => 1
1169 1180 assert_response :success
1170 1181 assert_template 'new'
1171 1182
1172 1183 assert_no_tag 'input', :attributes => {:name => 'issue[is_private]'}
1173 1184 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
1174 1185 assert_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
1175 1186 assert_tag 'input', :attributes => {:name => 'issue[subject]'}
1176 1187 assert_tag 'textarea', :attributes => {:name => 'issue[description]'}
1177 1188 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
1178 1189 assert_tag 'select', :attributes => {:name => 'issue[priority_id]'}
1179 1190 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
1180 1191 assert_tag 'select', :attributes => {:name => 'issue[category_id]'}
1181 1192 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
1182 1193 assert_no_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
1183 1194 assert_tag 'input', :attributes => {:name => 'issue[start_date]'}
1184 1195 assert_tag 'input', :attributes => {:name => 'issue[due_date]'}
1185 1196 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
1186 1197 assert_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]', :value => 'Default string' }
1187 1198 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
1188 1199 end
1189 1200
1190 1201 def test_get_new_with_multi_custom_field
1191 1202 field = IssueCustomField.find(1)
1192 1203 field.update_attribute :multiple, true
1193 1204
1194 1205 @request.session[:user_id] = 2
1195 1206 get :new, :project_id => 1, :tracker_id => 1
1196 1207 assert_response :success
1197 1208 assert_template 'new'
1198 1209
1199 1210 assert_tag 'select',
1200 1211 :attributes => {:name => 'issue[custom_field_values][1][]', :multiple => 'multiple'},
1201 1212 :children => {:count => 3},
1202 1213 :child => {:tag => 'option', :attributes => {:value => 'MySQL'}, :content => 'MySQL'}
1203 1214 assert_tag 'input',
1204 1215 :attributes => {:name => 'issue[custom_field_values][1][]', :value => ''}
1205 1216 end
1206 1217
1207 1218 def test_get_new_with_multi_user_custom_field
1208 1219 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1209 1220 :tracker_ids => [1], :is_for_all => true)
1210 1221
1211 1222 @request.session[:user_id] = 2
1212 1223 get :new, :project_id => 1, :tracker_id => 1
1213 1224 assert_response :success
1214 1225 assert_template 'new'
1215 1226
1216 1227 assert_tag 'select',
1217 1228 :attributes => {:name => "issue[custom_field_values][#{field.id}][]", :multiple => 'multiple'},
1218 1229 :children => {:count => Project.find(1).users.count},
1219 1230 :child => {:tag => 'option', :attributes => {:value => '2'}, :content => 'John Smith'}
1220 1231 assert_tag 'input',
1221 1232 :attributes => {:name => "issue[custom_field_values][#{field.id}][]", :value => ''}
1222 1233 end
1223 1234
1224 1235 def test_get_new_without_default_start_date_is_creation_date
1225 1236 Setting.default_issue_start_date_to_creation_date = 0
1226 1237
1227 1238 @request.session[:user_id] = 2
1228 1239 get :new, :project_id => 1, :tracker_id => 1
1229 1240 assert_response :success
1230 1241 assert_template 'new'
1231 1242
1232 1243 assert_tag :tag => 'input', :attributes => { :name => 'issue[start_date]',
1233 1244 :value => nil }
1234 1245 end
1235 1246
1236 1247 def test_get_new_with_default_start_date_is_creation_date
1237 1248 Setting.default_issue_start_date_to_creation_date = 1
1238 1249
1239 1250 @request.session[:user_id] = 2
1240 1251 get :new, :project_id => 1, :tracker_id => 1
1241 1252 assert_response :success
1242 1253 assert_template 'new'
1243 1254
1244 1255 assert_tag :tag => 'input', :attributes => { :name => 'issue[start_date]',
1245 1256 :value => Date.today.to_s }
1246 1257 end
1247 1258
1248 1259 def test_get_new_form_should_allow_attachment_upload
1249 1260 @request.session[:user_id] = 2
1250 1261 get :new, :project_id => 1, :tracker_id => 1
1251 1262
1252 1263 assert_tag :tag => 'form',
1253 1264 :attributes => {:id => 'issue-form', :method => 'post', :enctype => 'multipart/form-data'},
1254 1265 :descendant => {
1255 1266 :tag => 'input',
1256 1267 :attributes => {:type => 'file', :name => 'attachments[1][file]'}
1257 1268 }
1258 1269 end
1259 1270
1260 1271 def test_get_new_without_tracker_id
1261 1272 @request.session[:user_id] = 2
1262 1273 get :new, :project_id => 1
1263 1274 assert_response :success
1264 1275 assert_template 'new'
1265 1276
1266 1277 issue = assigns(:issue)
1267 1278 assert_not_nil issue
1268 1279 assert_equal Project.find(1).trackers.first, issue.tracker
1269 1280 end
1270 1281
1271 1282 def test_get_new_with_no_default_status_should_display_an_error
1272 1283 @request.session[:user_id] = 2
1273 1284 IssueStatus.delete_all
1274 1285
1275 1286 get :new, :project_id => 1
1276 1287 assert_response 500
1277 1288 assert_error_tag :content => /No default issue/
1278 1289 end
1279 1290
1280 1291 def test_get_new_with_no_tracker_should_display_an_error
1281 1292 @request.session[:user_id] = 2
1282 1293 Tracker.delete_all
1283 1294
1284 1295 get :new, :project_id => 1
1285 1296 assert_response 500
1286 1297 assert_error_tag :content => /No tracker/
1287 1298 end
1288 1299
1289 1300 def test_update_new_form
1290 1301 @request.session[:user_id] = 2
1291 1302 xhr :post, :new, :project_id => 1,
1292 1303 :issue => {:tracker_id => 2,
1293 1304 :subject => 'This is the test_new issue',
1294 1305 :description => 'This is the description',
1295 1306 :priority_id => 5}
1296 1307 assert_response :success
1297 1308 assert_template 'attributes'
1298 1309
1299 1310 issue = assigns(:issue)
1300 1311 assert_kind_of Issue, issue
1301 1312 assert_equal 1, issue.project_id
1302 1313 assert_equal 2, issue.tracker_id
1303 1314 assert_equal 'This is the test_new issue', issue.subject
1304 1315 end
1305 1316
1306 1317 def test_post_create
1307 1318 @request.session[:user_id] = 2
1308 1319 assert_difference 'Issue.count' do
1309 1320 post :create, :project_id => 1,
1310 1321 :issue => {:tracker_id => 3,
1311 1322 :status_id => 2,
1312 1323 :subject => 'This is the test_new issue',
1313 1324 :description => 'This is the description',
1314 1325 :priority_id => 5,
1315 1326 :start_date => '2010-11-07',
1316 1327 :estimated_hours => '',
1317 1328 :custom_field_values => {'2' => 'Value for field 2'}}
1318 1329 end
1319 1330 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1320 1331
1321 1332 issue = Issue.find_by_subject('This is the test_new issue')
1322 1333 assert_not_nil issue
1323 1334 assert_equal 2, issue.author_id
1324 1335 assert_equal 3, issue.tracker_id
1325 1336 assert_equal 2, issue.status_id
1326 1337 assert_equal Date.parse('2010-11-07'), issue.start_date
1327 1338 assert_nil issue.estimated_hours
1328 1339 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
1329 1340 assert_not_nil v
1330 1341 assert_equal 'Value for field 2', v.value
1331 1342 end
1332 1343
1333 1344 def test_post_new_with_group_assignment
1334 1345 group = Group.find(11)
1335 1346 project = Project.find(1)
1336 1347 project.members << Member.new(:principal => group, :roles => [Role.first])
1337 1348
1338 1349 with_settings :issue_group_assignment => '1' do
1339 1350 @request.session[:user_id] = 2
1340 1351 assert_difference 'Issue.count' do
1341 1352 post :create, :project_id => project.id,
1342 1353 :issue => {:tracker_id => 3,
1343 1354 :status_id => 1,
1344 1355 :subject => 'This is the test_new_with_group_assignment issue',
1345 1356 :assigned_to_id => group.id}
1346 1357 end
1347 1358 end
1348 1359 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1349 1360
1350 1361 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
1351 1362 assert_not_nil issue
1352 1363 assert_equal group, issue.assigned_to
1353 1364 end
1354 1365
1355 1366 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
1356 1367 Setting.default_issue_start_date_to_creation_date = 0
1357 1368
1358 1369 @request.session[:user_id] = 2
1359 1370 assert_difference 'Issue.count' do
1360 1371 post :create, :project_id => 1,
1361 1372 :issue => {:tracker_id => 3,
1362 1373 :status_id => 2,
1363 1374 :subject => 'This is the test_new issue',
1364 1375 :description => 'This is the description',
1365 1376 :priority_id => 5,
1366 1377 :estimated_hours => '',
1367 1378 :custom_field_values => {'2' => 'Value for field 2'}}
1368 1379 end
1369 1380 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1370 1381
1371 1382 issue = Issue.find_by_subject('This is the test_new issue')
1372 1383 assert_not_nil issue
1373 1384 assert_nil issue.start_date
1374 1385 end
1375 1386
1376 1387 def test_post_create_without_start_date_and_default_start_date_is_creation_date
1377 1388 Setting.default_issue_start_date_to_creation_date = 1
1378 1389
1379 1390 @request.session[:user_id] = 2
1380 1391 assert_difference 'Issue.count' do
1381 1392 post :create, :project_id => 1,
1382 1393 :issue => {:tracker_id => 3,
1383 1394 :status_id => 2,
1384 1395 :subject => 'This is the test_new issue',
1385 1396 :description => 'This is the description',
1386 1397 :priority_id => 5,
1387 1398 :estimated_hours => '',
1388 1399 :custom_field_values => {'2' => 'Value for field 2'}}
1389 1400 end
1390 1401 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1391 1402
1392 1403 issue = Issue.find_by_subject('This is the test_new issue')
1393 1404 assert_not_nil issue
1394 1405 assert_equal Date.today, issue.start_date
1395 1406 end
1396 1407
1397 1408 def test_post_create_and_continue
1398 1409 @request.session[:user_id] = 2
1399 1410 assert_difference 'Issue.count' do
1400 1411 post :create, :project_id => 1,
1401 1412 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
1402 1413 :continue => ''
1403 1414 end
1404 1415
1405 1416 issue = Issue.first(:order => 'id DESC')
1406 1417 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
1407 1418 assert_not_nil flash[:notice], "flash was not set"
1408 1419 assert flash[:notice].include?("<a href='/issues/#{issue.id}'>##{issue.id}</a>"), "issue link not found in flash: #{flash[:notice]}"
1409 1420 end
1410 1421
1411 1422 def test_post_create_without_custom_fields_param
1412 1423 @request.session[:user_id] = 2
1413 1424 assert_difference 'Issue.count' do
1414 1425 post :create, :project_id => 1,
1415 1426 :issue => {:tracker_id => 1,
1416 1427 :subject => 'This is the test_new issue',
1417 1428 :description => 'This is the description',
1418 1429 :priority_id => 5}
1419 1430 end
1420 1431 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1421 1432 end
1422 1433
1423 1434 def test_post_create_with_multi_custom_field
1424 1435 field = IssueCustomField.find_by_name('Database')
1425 1436 field.update_attribute(:multiple, true)
1426 1437
1427 1438 @request.session[:user_id] = 2
1428 1439 assert_difference 'Issue.count' do
1429 1440 post :create, :project_id => 1,
1430 1441 :issue => {:tracker_id => 1,
1431 1442 :subject => 'This is the test_new issue',
1432 1443 :description => 'This is the description',
1433 1444 :priority_id => 5,
1434 1445 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
1435 1446 end
1436 1447 assert_response 302
1437 1448 issue = Issue.first(:order => 'id DESC')
1438 1449 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
1439 1450 end
1440 1451
1441 1452 def test_post_create_with_empty_multi_custom_field
1442 1453 field = IssueCustomField.find_by_name('Database')
1443 1454 field.update_attribute(:multiple, true)
1444 1455
1445 1456 @request.session[:user_id] = 2
1446 1457 assert_difference 'Issue.count' do
1447 1458 post :create, :project_id => 1,
1448 1459 :issue => {:tracker_id => 1,
1449 1460 :subject => 'This is the test_new issue',
1450 1461 :description => 'This is the description',
1451 1462 :priority_id => 5,
1452 1463 :custom_field_values => {'1' => ['']}}
1453 1464 end
1454 1465 assert_response 302
1455 1466 issue = Issue.first(:order => 'id DESC')
1456 1467 assert_equal [''], issue.custom_field_value(1).sort
1457 1468 end
1458 1469
1459 1470 def test_post_create_with_multi_user_custom_field
1460 1471 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1461 1472 :tracker_ids => [1], :is_for_all => true)
1462 1473
1463 1474 @request.session[:user_id] = 2
1464 1475 assert_difference 'Issue.count' do
1465 1476 post :create, :project_id => 1,
1466 1477 :issue => {:tracker_id => 1,
1467 1478 :subject => 'This is the test_new issue',
1468 1479 :description => 'This is the description',
1469 1480 :priority_id => 5,
1470 1481 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
1471 1482 end
1472 1483 assert_response 302
1473 1484 issue = Issue.first(:order => 'id DESC')
1474 1485 assert_equal ['2', '3'], issue.custom_field_value(field).sort
1475 1486 end
1476 1487
1477 1488 def test_post_create_with_required_custom_field_and_without_custom_fields_param
1478 1489 field = IssueCustomField.find_by_name('Database')
1479 1490 field.update_attribute(:is_required, true)
1480 1491
1481 1492 @request.session[:user_id] = 2
1482 1493 assert_no_difference 'Issue.count' do
1483 1494 post :create, :project_id => 1,
1484 1495 :issue => {:tracker_id => 1,
1485 1496 :subject => 'This is the test_new issue',
1486 1497 :description => 'This is the description',
1487 1498 :priority_id => 5}
1488 1499 end
1489 1500 assert_response :success
1490 1501 assert_template 'new'
1491 1502 issue = assigns(:issue)
1492 1503 assert_not_nil issue
1493 1504 assert_error_tag :content => /Database can't be blank/
1494 1505 end
1495 1506
1496 1507 def test_post_create_with_watchers
1497 1508 @request.session[:user_id] = 2
1498 1509 ActionMailer::Base.deliveries.clear
1499 1510
1500 1511 assert_difference 'Watcher.count', 2 do
1501 1512 post :create, :project_id => 1,
1502 1513 :issue => {:tracker_id => 1,
1503 1514 :subject => 'This is a new issue with watchers',
1504 1515 :description => 'This is the description',
1505 1516 :priority_id => 5,
1506 1517 :watcher_user_ids => ['2', '3']}
1507 1518 end
1508 1519 issue = Issue.find_by_subject('This is a new issue with watchers')
1509 1520 assert_not_nil issue
1510 1521 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
1511 1522
1512 1523 # Watchers added
1513 1524 assert_equal [2, 3], issue.watcher_user_ids.sort
1514 1525 assert issue.watched_by?(User.find(3))
1515 1526 # Watchers notified
1516 1527 mail = ActionMailer::Base.deliveries.last
1517 1528 assert_kind_of TMail::Mail, mail
1518 1529 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
1519 1530 end
1520 1531
1521 1532 def test_post_create_subissue
1522 1533 @request.session[:user_id] = 2
1523 1534
1524 1535 assert_difference 'Issue.count' do
1525 1536 post :create, :project_id => 1,
1526 1537 :issue => {:tracker_id => 1,
1527 1538 :subject => 'This is a child issue',
1528 1539 :parent_issue_id => 2}
1529 1540 end
1530 1541 issue = Issue.find_by_subject('This is a child issue')
1531 1542 assert_not_nil issue
1532 1543 assert_equal Issue.find(2), issue.parent
1533 1544 end
1534 1545
1535 1546 def test_post_create_subissue_with_non_numeric_parent_id
1536 1547 @request.session[:user_id] = 2
1537 1548
1538 1549 assert_difference 'Issue.count' do
1539 1550 post :create, :project_id => 1,
1540 1551 :issue => {:tracker_id => 1,
1541 1552 :subject => 'This is a child issue',
1542 1553 :parent_issue_id => 'ABC'}
1543 1554 end
1544 1555 issue = Issue.find_by_subject('This is a child issue')
1545 1556 assert_not_nil issue
1546 1557 assert_nil issue.parent
1547 1558 end
1548 1559
1549 1560 def test_post_create_private
1550 1561 @request.session[:user_id] = 2
1551 1562
1552 1563 assert_difference 'Issue.count' do
1553 1564 post :create, :project_id => 1,
1554 1565 :issue => {:tracker_id => 1,
1555 1566 :subject => 'This is a private issue',
1556 1567 :is_private => '1'}
1557 1568 end
1558 1569 issue = Issue.first(:order => 'id DESC')
1559 1570 assert issue.is_private?
1560 1571 end
1561 1572
1562 1573 def test_post_create_private_with_set_own_issues_private_permission
1563 1574 role = Role.find(1)
1564 1575 role.remove_permission! :set_issues_private
1565 1576 role.add_permission! :set_own_issues_private
1566 1577
1567 1578 @request.session[:user_id] = 2
1568 1579
1569 1580 assert_difference 'Issue.count' do
1570 1581 post :create, :project_id => 1,
1571 1582 :issue => {:tracker_id => 1,
1572 1583 :subject => 'This is a private issue',
1573 1584 :is_private => '1'}
1574 1585 end
1575 1586 issue = Issue.first(:order => 'id DESC')
1576 1587 assert issue.is_private?
1577 1588 end
1578 1589
1579 1590 def test_post_create_should_send_a_notification
1580 1591 ActionMailer::Base.deliveries.clear
1581 1592 @request.session[:user_id] = 2
1582 1593 assert_difference 'Issue.count' do
1583 1594 post :create, :project_id => 1,
1584 1595 :issue => {:tracker_id => 3,
1585 1596 :subject => 'This is the test_new issue',
1586 1597 :description => 'This is the description',
1587 1598 :priority_id => 5,
1588 1599 :estimated_hours => '',
1589 1600 :custom_field_values => {'2' => 'Value for field 2'}}
1590 1601 end
1591 1602 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1592 1603
1593 1604 assert_equal 1, ActionMailer::Base.deliveries.size
1594 1605 end
1595 1606
1596 1607 def test_post_create_should_preserve_fields_values_on_validation_failure
1597 1608 @request.session[:user_id] = 2
1598 1609 post :create, :project_id => 1,
1599 1610 :issue => {:tracker_id => 1,
1600 1611 # empty subject
1601 1612 :subject => '',
1602 1613 :description => 'This is a description',
1603 1614 :priority_id => 6,
1604 1615 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
1605 1616 assert_response :success
1606 1617 assert_template 'new'
1607 1618
1608 1619 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
1609 1620 :content => 'This is a description'
1610 1621 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
1611 1622 :child => { :tag => 'option', :attributes => { :selected => 'selected',
1612 1623 :value => '6' },
1613 1624 :content => 'High' }
1614 1625 # Custom fields
1615 1626 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
1616 1627 :child => { :tag => 'option', :attributes => { :selected => 'selected',
1617 1628 :value => 'Oracle' },
1618 1629 :content => 'Oracle' }
1619 1630 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
1620 1631 :value => 'Value for field 2'}
1621 1632 end
1622 1633
1623 1634 def test_post_create_should_ignore_non_safe_attributes
1624 1635 @request.session[:user_id] = 2
1625 1636 assert_nothing_raised do
1626 1637 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
1627 1638 end
1628 1639 end
1629 1640
1630 1641 def test_post_create_with_attachment
1631 1642 set_tmp_attachments_directory
1632 1643 @request.session[:user_id] = 2
1633 1644
1634 1645 assert_difference 'Issue.count' do
1635 1646 assert_difference 'Attachment.count' do
1636 1647 post :create, :project_id => 1,
1637 1648 :issue => { :tracker_id => '1', :subject => 'With attachment' },
1638 1649 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
1639 1650 end
1640 1651 end
1641 1652
1642 1653 issue = Issue.first(:order => 'id DESC')
1643 1654 attachment = Attachment.first(:order => 'id DESC')
1644 1655
1645 1656 assert_equal issue, attachment.container
1646 1657 assert_equal 2, attachment.author_id
1647 1658 assert_equal 'testfile.txt', attachment.filename
1648 1659 assert_equal 'text/plain', attachment.content_type
1649 1660 assert_equal 'test file', attachment.description
1650 1661 assert_equal 59, attachment.filesize
1651 1662 assert File.exists?(attachment.diskfile)
1652 1663 assert_equal 59, File.size(attachment.diskfile)
1653 1664 end
1654 1665
1655 1666 context "without workflow privilege" do
1656 1667 setup do
1657 1668 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
1658 1669 Role.anonymous.add_permission! :add_issues, :add_issue_notes
1659 1670 end
1660 1671
1661 1672 context "#new" do
1662 1673 should "propose default status only" do
1663 1674 get :new, :project_id => 1
1664 1675 assert_response :success
1665 1676 assert_template 'new'
1666 1677 assert_tag :tag => 'select',
1667 1678 :attributes => {:name => 'issue[status_id]'},
1668 1679 :children => {:count => 1},
1669 1680 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
1670 1681 end
1671 1682
1672 1683 should "accept default status" do
1673 1684 assert_difference 'Issue.count' do
1674 1685 post :create, :project_id => 1,
1675 1686 :issue => {:tracker_id => 1,
1676 1687 :subject => 'This is an issue',
1677 1688 :status_id => 1}
1678 1689 end
1679 1690 issue = Issue.last(:order => 'id')
1680 1691 assert_equal IssueStatus.default, issue.status
1681 1692 end
1682 1693
1683 1694 should "ignore unauthorized status" do
1684 1695 assert_difference 'Issue.count' do
1685 1696 post :create, :project_id => 1,
1686 1697 :issue => {:tracker_id => 1,
1687 1698 :subject => 'This is an issue',
1688 1699 :status_id => 3}
1689 1700 end
1690 1701 issue = Issue.last(:order => 'id')
1691 1702 assert_equal IssueStatus.default, issue.status
1692 1703 end
1693 1704 end
1694 1705
1695 1706 context "#update" do
1696 1707 should "ignore status change" do
1697 1708 assert_difference 'Journal.count' do
1698 1709 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
1699 1710 end
1700 1711 assert_equal 1, Issue.find(1).status_id
1701 1712 end
1702 1713
1703 1714 should "ignore attributes changes" do
1704 1715 assert_difference 'Journal.count' do
1705 1716 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
1706 1717 end
1707 1718 issue = Issue.find(1)
1708 1719 assert_equal "Can't print recipes", issue.subject
1709 1720 assert_nil issue.assigned_to
1710 1721 end
1711 1722 end
1712 1723 end
1713 1724
1714 1725 context "with workflow privilege" do
1715 1726 setup do
1716 1727 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
1717 1728 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
1718 1729 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
1719 1730 Role.anonymous.add_permission! :add_issues, :add_issue_notes
1720 1731 end
1721 1732
1722 1733 context "#update" do
1723 1734 should "accept authorized status" do
1724 1735 assert_difference 'Journal.count' do
1725 1736 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
1726 1737 end
1727 1738 assert_equal 3, Issue.find(1).status_id
1728 1739 end
1729 1740
1730 1741 should "ignore unauthorized status" do
1731 1742 assert_difference 'Journal.count' do
1732 1743 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
1733 1744 end
1734 1745 assert_equal 1, Issue.find(1).status_id
1735 1746 end
1736 1747
1737 1748 should "accept authorized attributes changes" do
1738 1749 assert_difference 'Journal.count' do
1739 1750 put :update, :id => 1, :notes => 'just trying', :issue => {:assigned_to_id => 2}
1740 1751 end
1741 1752 issue = Issue.find(1)
1742 1753 assert_equal 2, issue.assigned_to_id
1743 1754 end
1744 1755
1745 1756 should "ignore unauthorized attributes changes" do
1746 1757 assert_difference 'Journal.count' do
1747 1758 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed'}
1748 1759 end
1749 1760 issue = Issue.find(1)
1750 1761 assert_equal "Can't print recipes", issue.subject
1751 1762 end
1752 1763 end
1753 1764
1754 1765 context "and :edit_issues permission" do
1755 1766 setup do
1756 1767 Role.anonymous.add_permission! :add_issues, :edit_issues
1757 1768 end
1758 1769
1759 1770 should "accept authorized status" do
1760 1771 assert_difference 'Journal.count' do
1761 1772 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
1762 1773 end
1763 1774 assert_equal 3, Issue.find(1).status_id
1764 1775 end
1765 1776
1766 1777 should "ignore unauthorized status" do
1767 1778 assert_difference 'Journal.count' do
1768 1779 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
1769 1780 end
1770 1781 assert_equal 1, Issue.find(1).status_id
1771 1782 end
1772 1783
1773 1784 should "accept authorized attributes changes" do
1774 1785 assert_difference 'Journal.count' do
1775 1786 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
1776 1787 end
1777 1788 issue = Issue.find(1)
1778 1789 assert_equal "changed", issue.subject
1779 1790 assert_equal 2, issue.assigned_to_id
1780 1791 end
1781 1792 end
1782 1793 end
1783 1794
1784 1795 def test_new_as_copy
1785 1796 @request.session[:user_id] = 2
1786 1797 get :new, :project_id => 1, :copy_from => 1
1787 1798
1788 1799 assert_response :success
1789 1800 assert_template 'new'
1790 1801
1791 1802 assert_not_nil assigns(:issue)
1792 1803 orig = Issue.find(1)
1793 1804 assert_equal 1, assigns(:issue).project_id
1794 1805 assert_equal orig.subject, assigns(:issue).subject
1795 1806 assert assigns(:issue).copy?
1796 1807
1797 1808 assert_tag 'form', :attributes => {:id => 'issue-form', :action => '/projects/ecookbook/issues'}
1798 1809 assert_tag 'select', :attributes => {:name => 'issue[project_id]'}
1799 1810 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
1800 1811 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}, :content => 'eCookbook'}
1801 1812 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
1802 1813 :child => {:tag => 'option', :attributes => {:value => '2', :selected => nil}, :content => 'OnlineStore'}
1803 1814 assert_tag 'input', :attributes => {:name => 'copy_from', :value => '1'}
1804 1815 end
1805 1816
1806 1817 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
1807 1818 @request.session[:user_id] = 2
1808 1819 issue = Issue.find(3)
1809 1820 assert issue.attachments.count > 0
1810 1821 get :new, :project_id => 1, :copy_from => 3
1811 1822
1812 1823 assert_tag 'input', :attributes => {:name => 'copy_attachments', :type => 'checkbox', :checked => 'checked', :value => '1'}
1813 1824 end
1814 1825
1815 1826 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
1816 1827 @request.session[:user_id] = 2
1817 1828 issue = Issue.find(3)
1818 1829 issue.attachments.delete_all
1819 1830 get :new, :project_id => 1, :copy_from => 3
1820 1831
1821 1832 assert_no_tag 'input', :attributes => {:name => 'copy_attachments', :type => 'checkbox', :checked => 'checked', :value => '1'}
1822 1833 end
1823 1834
1824 1835 def test_new_as_copy_with_invalid_issue_should_respond_with_404
1825 1836 @request.session[:user_id] = 2
1826 1837 get :new, :project_id => 1, :copy_from => 99999
1827 1838 assert_response 404
1828 1839 end
1829 1840
1830 1841 def test_create_as_copy_on_different_project
1831 1842 @request.session[:user_id] = 2
1832 1843 assert_difference 'Issue.count' do
1833 1844 post :create, :project_id => 1, :copy_from => 1,
1834 1845 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
1835 1846
1836 1847 assert_not_nil assigns(:issue)
1837 1848 assert assigns(:issue).copy?
1838 1849 end
1839 1850 issue = Issue.first(:order => 'id DESC')
1840 1851 assert_redirected_to "/issues/#{issue.id}"
1841 1852
1842 1853 assert_equal 2, issue.project_id
1843 1854 assert_equal 3, issue.tracker_id
1844 1855 assert_equal 'Copy', issue.subject
1845 1856 end
1846 1857
1847 1858 def test_create_as_copy_should_copy_attachments
1848 1859 @request.session[:user_id] = 2
1849 1860 issue = Issue.find(3)
1850 1861 count = issue.attachments.count
1851 1862 assert count > 0
1852 1863
1853 1864 assert_difference 'Issue.count' do
1854 1865 assert_difference 'Attachment.count', count do
1855 1866 assert_no_difference 'Journal.count' do
1856 1867 post :create, :project_id => 1, :copy_from => 3,
1857 1868 :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'},
1858 1869 :copy_attachments => '1'
1859 1870 end
1860 1871 end
1861 1872 end
1862 1873 copy = Issue.first(:order => 'id DESC')
1863 1874 assert_equal count, copy.attachments.count
1864 1875 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
1865 1876 end
1866 1877
1867 1878 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
1868 1879 @request.session[:user_id] = 2
1869 1880 issue = Issue.find(3)
1870 1881 count = issue.attachments.count
1871 1882 assert count > 0
1872 1883
1873 1884 assert_difference 'Issue.count' do
1874 1885 assert_no_difference 'Attachment.count' do
1875 1886 assert_no_difference 'Journal.count' do
1876 1887 post :create, :project_id => 1, :copy_from => 3,
1877 1888 :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'}
1878 1889 end
1879 1890 end
1880 1891 end
1881 1892 copy = Issue.first(:order => 'id DESC')
1882 1893 assert_equal 0, copy.attachments.count
1883 1894 end
1884 1895
1885 1896 def test_create_as_copy_with_attachments_should_add_new_files
1886 1897 @request.session[:user_id] = 2
1887 1898 issue = Issue.find(3)
1888 1899 count = issue.attachments.count
1889 1900 assert count > 0
1890 1901
1891 1902 assert_difference 'Issue.count' do
1892 1903 assert_difference 'Attachment.count', count + 1 do
1893 1904 assert_no_difference 'Journal.count' do
1894 1905 post :create, :project_id => 1, :copy_from => 3,
1895 1906 :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'},
1896 1907 :copy_attachments => '1',
1897 1908 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
1898 1909 end
1899 1910 end
1900 1911 end
1901 1912 copy = Issue.first(:order => 'id DESC')
1902 1913 assert_equal count + 1, copy.attachments.count
1903 1914 end
1904 1915
1905 1916 def test_create_as_copy_with_failure
1906 1917 @request.session[:user_id] = 2
1907 1918 post :create, :project_id => 1, :copy_from => 1,
1908 1919 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
1909 1920
1910 1921 assert_response :success
1911 1922 assert_template 'new'
1912 1923
1913 1924 assert_not_nil assigns(:issue)
1914 1925 assert assigns(:issue).copy?
1915 1926
1916 1927 assert_tag 'form', :attributes => {:id => 'issue-form', :action => '/projects/ecookbook/issues'}
1917 1928 assert_tag 'select', :attributes => {:name => 'issue[project_id]'}
1918 1929 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
1919 1930 :child => {:tag => 'option', :attributes => {:value => '1', :selected => nil}, :content => 'eCookbook'}
1920 1931 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
1921 1932 :child => {:tag => 'option', :attributes => {:value => '2', :selected => 'selected'}, :content => 'OnlineStore'}
1922 1933 assert_tag 'input', :attributes => {:name => 'copy_from', :value => '1'}
1923 1934 end
1924 1935
1925 1936 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
1926 1937 @request.session[:user_id] = 2
1927 1938 assert !User.find(2).member_of?(Project.find(4))
1928 1939
1929 1940 assert_difference 'Issue.count' do
1930 1941 post :create, :project_id => 1, :copy_from => 1,
1931 1942 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
1932 1943 end
1933 1944 issue = Issue.first(:order => 'id DESC')
1934 1945 assert_equal 1, issue.project_id
1935 1946 end
1936 1947
1937 1948 def test_get_edit
1938 1949 @request.session[:user_id] = 2
1939 1950 get :edit, :id => 1
1940 1951 assert_response :success
1941 1952 assert_template 'edit'
1942 1953 assert_not_nil assigns(:issue)
1943 1954 assert_equal Issue.find(1), assigns(:issue)
1944 1955
1945 1956 # Be sure we don't display inactive IssuePriorities
1946 1957 assert ! IssuePriority.find(15).active?
1947 1958 assert_no_tag :option, :attributes => {:value => '15'},
1948 1959 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
1949 1960 end
1950 1961
1951 1962 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
1952 1963 @request.session[:user_id] = 2
1953 1964 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
1954 1965
1955 1966 get :edit, :id => 1
1956 1967 assert_tag 'input', :attributes => {:name => 'time_entry[hours]'}
1957 1968 end
1958 1969
1959 1970 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
1960 1971 @request.session[:user_id] = 2
1961 1972 Role.find_by_name('Manager').remove_permission! :log_time
1962 1973
1963 1974 get :edit, :id => 1
1964 1975 assert_no_tag 'input', :attributes => {:name => 'time_entry[hours]'}
1965 1976 end
1966 1977
1967 1978 def test_get_edit_with_params
1968 1979 @request.session[:user_id] = 2
1969 1980 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
1970 1981 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => TimeEntryActivity.first.id }
1971 1982 assert_response :success
1972 1983 assert_template 'edit'
1973 1984
1974 1985 issue = assigns(:issue)
1975 1986 assert_not_nil issue
1976 1987
1977 1988 assert_equal 5, issue.status_id
1978 1989 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
1979 1990 :child => { :tag => 'option',
1980 1991 :content => 'Closed',
1981 1992 :attributes => { :selected => 'selected' } }
1982 1993
1983 1994 assert_equal 7, issue.priority_id
1984 1995 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
1985 1996 :child => { :tag => 'option',
1986 1997 :content => 'Urgent',
1987 1998 :attributes => { :selected => 'selected' } }
1988 1999
1989 2000 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => '2.5' }
1990 2001 assert_tag :select, :attributes => { :name => 'time_entry[activity_id]' },
1991 2002 :child => { :tag => 'option',
1992 2003 :attributes => { :selected => 'selected', :value => TimeEntryActivity.first.id } }
1993 2004 assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => 'test_get_edit_with_params' }
1994 2005 end
1995 2006
1996 2007 def test_get_edit_with_multi_custom_field
1997 2008 field = CustomField.find(1)
1998 2009 field.update_attribute :multiple, true
1999 2010 issue = Issue.find(1)
2000 2011 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2001 2012 issue.save!
2002 2013
2003 2014 @request.session[:user_id] = 2
2004 2015 get :edit, :id => 1
2005 2016 assert_response :success
2006 2017 assert_template 'edit'
2007 2018
2008 2019 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]', :multiple => 'multiple'}
2009 2020 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]'},
2010 2021 :child => {:tag => 'option', :attributes => {:value => 'MySQL', :selected => 'selected'}}
2011 2022 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]'},
2012 2023 :child => {:tag => 'option', :attributes => {:value => 'PostgreSQL', :selected => nil}}
2013 2024 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]'},
2014 2025 :child => {:tag => 'option', :attributes => {:value => 'Oracle', :selected => 'selected'}}
2015 2026 end
2016 2027
2017 2028 def test_update_edit_form
2018 2029 @request.session[:user_id] = 2
2019 2030 xhr :put, :new, :project_id => 1,
2020 2031 :id => 1,
2021 2032 :issue => {:tracker_id => 2,
2022 2033 :subject => 'This is the test_new issue',
2023 2034 :description => 'This is the description',
2024 2035 :priority_id => 5}
2025 2036 assert_response :success
2026 2037 assert_template 'attributes'
2027 2038
2028 2039 issue = assigns(:issue)
2029 2040 assert_kind_of Issue, issue
2030 2041 assert_equal 1, issue.id
2031 2042 assert_equal 1, issue.project_id
2032 2043 assert_equal 2, issue.tracker_id
2033 2044 assert_equal 'This is the test_new issue', issue.subject
2034 2045 end
2035 2046
2036 2047 def test_update_edit_form_with_project_change
2037 2048 @request.session[:user_id] = 2
2038 2049 xhr :put, :new, :project_id => 1,
2039 2050 :id => 1,
2040 2051 :project_change => '1',
2041 2052 :issue => {:project_id => 2,
2042 2053 :tracker_id => 2,
2043 2054 :subject => 'This is the test_new issue',
2044 2055 :description => 'This is the description',
2045 2056 :priority_id => 5}
2046 2057 assert_response :success
2047 2058 assert_template 'form'
2048 2059
2049 2060 issue = assigns(:issue)
2050 2061 assert_kind_of Issue, issue
2051 2062 assert_equal 1, issue.id
2052 2063 assert_equal 2, issue.project_id
2053 2064 assert_equal 2, issue.tracker_id
2054 2065 assert_equal 'This is the test_new issue', issue.subject
2055 2066 end
2056 2067
2057 2068 def test_update_using_invalid_http_verbs
2058 2069 @request.session[:user_id] = 2
2059 2070 subject = 'Updated by an invalid http verb'
2060 2071
2061 2072 get :update, :id => 1, :issue => {:subject => subject}
2062 2073 assert_not_equal subject, Issue.find(1).subject
2063 2074
2064 2075 post :update, :id => 1, :issue => {:subject => subject}
2065 2076 assert_not_equal subject, Issue.find(1).subject
2066 2077
2067 2078 delete :update, :id => 1, :issue => {:subject => subject}
2068 2079 assert_not_equal subject, Issue.find(1).subject
2069 2080 end
2070 2081
2071 2082 def test_put_update_without_custom_fields_param
2072 2083 @request.session[:user_id] = 2
2073 2084 ActionMailer::Base.deliveries.clear
2074 2085
2075 2086 issue = Issue.find(1)
2076 2087 assert_equal '125', issue.custom_value_for(2).value
2077 2088 old_subject = issue.subject
2078 2089 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
2079 2090
2080 2091 assert_difference('Journal.count') do
2081 2092 assert_difference('JournalDetail.count', 2) do
2082 2093 put :update, :id => 1, :issue => {:subject => new_subject,
2083 2094 :priority_id => '6',
2084 2095 :category_id => '1' # no change
2085 2096 }
2086 2097 end
2087 2098 end
2088 2099 assert_redirected_to :action => 'show', :id => '1'
2089 2100 issue.reload
2090 2101 assert_equal new_subject, issue.subject
2091 2102 # Make sure custom fields were not cleared
2092 2103 assert_equal '125', issue.custom_value_for(2).value
2093 2104
2094 2105 mail = ActionMailer::Base.deliveries.last
2095 2106 assert_kind_of TMail::Mail, mail
2096 2107 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2097 2108 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
2098 2109 end
2099 2110
2100 2111 def test_put_update_with_project_change
2101 2112 @request.session[:user_id] = 2
2102 2113 ActionMailer::Base.deliveries.clear
2103 2114
2104 2115 assert_difference('Journal.count') do
2105 2116 assert_difference('JournalDetail.count', 3) do
2106 2117 put :update, :id => 1, :issue => {:project_id => '2',
2107 2118 :tracker_id => '1', # no change
2108 2119 :priority_id => '6',
2109 2120 :category_id => '3'
2110 2121 }
2111 2122 end
2112 2123 end
2113 2124 assert_redirected_to :action => 'show', :id => '1'
2114 2125 issue = Issue.find(1)
2115 2126 assert_equal 2, issue.project_id
2116 2127 assert_equal 1, issue.tracker_id
2117 2128 assert_equal 6, issue.priority_id
2118 2129 assert_equal 3, issue.category_id
2119 2130
2120 2131 mail = ActionMailer::Base.deliveries.last
2121 2132 assert_not_nil mail
2122 2133 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2123 2134 assert mail.body.include?("Project changed from eCookbook to OnlineStore")
2124 2135 end
2125 2136
2126 2137 def test_put_update_with_tracker_change
2127 2138 @request.session[:user_id] = 2
2128 2139 ActionMailer::Base.deliveries.clear
2129 2140
2130 2141 assert_difference('Journal.count') do
2131 2142 assert_difference('JournalDetail.count', 2) do
2132 2143 put :update, :id => 1, :issue => {:project_id => '1',
2133 2144 :tracker_id => '2',
2134 2145 :priority_id => '6'
2135 2146 }
2136 2147 end
2137 2148 end
2138 2149 assert_redirected_to :action => 'show', :id => '1'
2139 2150 issue = Issue.find(1)
2140 2151 assert_equal 1, issue.project_id
2141 2152 assert_equal 2, issue.tracker_id
2142 2153 assert_equal 6, issue.priority_id
2143 2154 assert_equal 1, issue.category_id
2144 2155
2145 2156 mail = ActionMailer::Base.deliveries.last
2146 2157 assert_not_nil mail
2147 2158 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2148 2159 assert mail.body.include?("Tracker changed from Bug to Feature request")
2149 2160 end
2150 2161
2151 2162 def test_put_update_with_custom_field_change
2152 2163 @request.session[:user_id] = 2
2153 2164 issue = Issue.find(1)
2154 2165 assert_equal '125', issue.custom_value_for(2).value
2155 2166
2156 2167 assert_difference('Journal.count') do
2157 2168 assert_difference('JournalDetail.count', 3) do
2158 2169 put :update, :id => 1, :issue => {:subject => 'Custom field change',
2159 2170 :priority_id => '6',
2160 2171 :category_id => '1', # no change
2161 2172 :custom_field_values => { '2' => 'New custom value' }
2162 2173 }
2163 2174 end
2164 2175 end
2165 2176 assert_redirected_to :action => 'show', :id => '1'
2166 2177 issue.reload
2167 2178 assert_equal 'New custom value', issue.custom_value_for(2).value
2168 2179
2169 2180 mail = ActionMailer::Base.deliveries.last
2170 2181 assert_kind_of TMail::Mail, mail
2171 2182 assert mail.body.include?("Searchable field changed from 125 to New custom value")
2172 2183 end
2173 2184
2174 2185 def test_put_update_with_multi_custom_field_change
2175 2186 field = CustomField.find(1)
2176 2187 field.update_attribute :multiple, true
2177 2188 issue = Issue.find(1)
2178 2189 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2179 2190 issue.save!
2180 2191
2181 2192 @request.session[:user_id] = 2
2182 2193 assert_difference('Journal.count') do
2183 2194 assert_difference('JournalDetail.count', 3) do
2184 2195 put :update, :id => 1,
2185 2196 :issue => {
2186 2197 :subject => 'Custom field change',
2187 2198 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
2188 2199 }
2189 2200 end
2190 2201 end
2191 2202 assert_redirected_to :action => 'show', :id => '1'
2192 2203 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
2193 2204 end
2194 2205
2195 2206 def test_put_update_with_status_and_assignee_change
2196 2207 issue = Issue.find(1)
2197 2208 assert_equal 1, issue.status_id
2198 2209 @request.session[:user_id] = 2
2199 2210 assert_difference('TimeEntry.count', 0) do
2200 2211 put :update,
2201 2212 :id => 1,
2202 2213 :issue => { :status_id => 2, :assigned_to_id => 3 },
2203 2214 :notes => 'Assigned to dlopper',
2204 2215 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
2205 2216 end
2206 2217 assert_redirected_to :action => 'show', :id => '1'
2207 2218 issue.reload
2208 2219 assert_equal 2, issue.status_id
2209 2220 j = Journal.find(:first, :order => 'id DESC')
2210 2221 assert_equal 'Assigned to dlopper', j.notes
2211 2222 assert_equal 2, j.details.size
2212 2223
2213 2224 mail = ActionMailer::Base.deliveries.last
2214 2225 assert mail.body.include?("Status changed from New to Assigned")
2215 2226 # subject should contain the new status
2216 2227 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
2217 2228 end
2218 2229
2219 2230 def test_put_update_with_note_only
2220 2231 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
2221 2232 # anonymous user
2222 2233 put :update,
2223 2234 :id => 1,
2224 2235 :notes => notes
2225 2236 assert_redirected_to :action => 'show', :id => '1'
2226 2237 j = Journal.find(:first, :order => 'id DESC')
2227 2238 assert_equal notes, j.notes
2228 2239 assert_equal 0, j.details.size
2229 2240 assert_equal User.anonymous, j.user
2230 2241
2231 2242 mail = ActionMailer::Base.deliveries.last
2232 2243 assert mail.body.include?(notes)
2233 2244 end
2234 2245
2235 2246 def test_put_update_with_note_and_spent_time
2236 2247 @request.session[:user_id] = 2
2237 2248 spent_hours_before = Issue.find(1).spent_hours
2238 2249 assert_difference('TimeEntry.count') do
2239 2250 put :update,
2240 2251 :id => 1,
2241 2252 :notes => '2.5 hours added',
2242 2253 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
2243 2254 end
2244 2255 assert_redirected_to :action => 'show', :id => '1'
2245 2256
2246 2257 issue = Issue.find(1)
2247 2258
2248 2259 j = Journal.find(:first, :order => 'id DESC')
2249 2260 assert_equal '2.5 hours added', j.notes
2250 2261 assert_equal 0, j.details.size
2251 2262
2252 2263 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
2253 2264 assert_not_nil t
2254 2265 assert_equal 2.5, t.hours
2255 2266 assert_equal spent_hours_before + 2.5, issue.spent_hours
2256 2267 end
2257 2268
2258 2269 def test_put_update_with_attachment_only
2259 2270 set_tmp_attachments_directory
2260 2271
2261 2272 # Delete all fixtured journals, a race condition can occur causing the wrong
2262 2273 # journal to get fetched in the next find.
2263 2274 Journal.delete_all
2264 2275
2265 2276 # anonymous user
2266 2277 assert_difference 'Attachment.count' do
2267 2278 put :update, :id => 1,
2268 2279 :notes => '',
2269 2280 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2270 2281 end
2271 2282
2272 2283 assert_redirected_to :action => 'show', :id => '1'
2273 2284 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
2274 2285 assert j.notes.blank?
2275 2286 assert_equal 1, j.details.size
2276 2287 assert_equal 'testfile.txt', j.details.first.value
2277 2288 assert_equal User.anonymous, j.user
2278 2289
2279 2290 attachment = Attachment.first(:order => 'id DESC')
2280 2291 assert_equal Issue.find(1), attachment.container
2281 2292 assert_equal User.anonymous, attachment.author
2282 2293 assert_equal 'testfile.txt', attachment.filename
2283 2294 assert_equal 'text/plain', attachment.content_type
2284 2295 assert_equal 'test file', attachment.description
2285 2296 assert_equal 59, attachment.filesize
2286 2297 assert File.exists?(attachment.diskfile)
2287 2298 assert_equal 59, File.size(attachment.diskfile)
2288 2299
2289 2300 mail = ActionMailer::Base.deliveries.last
2290 2301 assert mail.body.include?('testfile.txt')
2291 2302 end
2292 2303
2293 2304 def test_put_update_with_attachment_that_fails_to_save
2294 2305 set_tmp_attachments_directory
2295 2306
2296 2307 # Delete all fixtured journals, a race condition can occur causing the wrong
2297 2308 # journal to get fetched in the next find.
2298 2309 Journal.delete_all
2299 2310
2300 2311 # Mock out the unsaved attachment
2301 2312 Attachment.any_instance.stubs(:create).returns(Attachment.new)
2302 2313
2303 2314 # anonymous user
2304 2315 put :update,
2305 2316 :id => 1,
2306 2317 :notes => '',
2307 2318 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
2308 2319 assert_redirected_to :action => 'show', :id => '1'
2309 2320 assert_equal '1 file(s) could not be saved.', flash[:warning]
2310 2321
2311 2322 end if Object.const_defined?(:Mocha)
2312 2323
2313 2324 def test_put_update_with_no_change
2314 2325 issue = Issue.find(1)
2315 2326 issue.journals.clear
2316 2327 ActionMailer::Base.deliveries.clear
2317 2328
2318 2329 put :update,
2319 2330 :id => 1,
2320 2331 :notes => ''
2321 2332 assert_redirected_to :action => 'show', :id => '1'
2322 2333
2323 2334 issue.reload
2324 2335 assert issue.journals.empty?
2325 2336 # No email should be sent
2326 2337 assert ActionMailer::Base.deliveries.empty?
2327 2338 end
2328 2339
2329 2340 def test_put_update_should_send_a_notification
2330 2341 @request.session[:user_id] = 2
2331 2342 ActionMailer::Base.deliveries.clear
2332 2343 issue = Issue.find(1)
2333 2344 old_subject = issue.subject
2334 2345 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
2335 2346
2336 2347 put :update, :id => 1, :issue => {:subject => new_subject,
2337 2348 :priority_id => '6',
2338 2349 :category_id => '1' # no change
2339 2350 }
2340 2351 assert_equal 1, ActionMailer::Base.deliveries.size
2341 2352 end
2342 2353
2343 2354 def test_put_update_with_invalid_spent_time_hours_only
2344 2355 @request.session[:user_id] = 2
2345 2356 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
2346 2357
2347 2358 assert_no_difference('Journal.count') do
2348 2359 put :update,
2349 2360 :id => 1,
2350 2361 :notes => notes,
2351 2362 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
2352 2363 end
2353 2364 assert_response :success
2354 2365 assert_template 'edit'
2355 2366
2356 2367 assert_error_tag :descendant => {:content => /Activity can't be blank/}
2357 2368 assert_tag :textarea, :attributes => { :name => 'notes' }, :content => notes
2358 2369 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
2359 2370 end
2360 2371
2361 2372 def test_put_update_with_invalid_spent_time_comments_only
2362 2373 @request.session[:user_id] = 2
2363 2374 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
2364 2375
2365 2376 assert_no_difference('Journal.count') do
2366 2377 put :update,
2367 2378 :id => 1,
2368 2379 :notes => notes,
2369 2380 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
2370 2381 end
2371 2382 assert_response :success
2372 2383 assert_template 'edit'
2373 2384
2374 2385 assert_error_tag :descendant => {:content => /Activity can't be blank/}
2375 2386 assert_error_tag :descendant => {:content => /Hours can't be blank/}
2376 2387 assert_tag :textarea, :attributes => { :name => 'notes' }, :content => notes
2377 2388 assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => "this is my comment" }
2378 2389 end
2379 2390
2380 2391 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
2381 2392 issue = Issue.find(2)
2382 2393 @request.session[:user_id] = 2
2383 2394
2384 2395 put :update,
2385 2396 :id => issue.id,
2386 2397 :issue => {
2387 2398 :fixed_version_id => 4
2388 2399 }
2389 2400
2390 2401 assert_response :redirect
2391 2402 issue.reload
2392 2403 assert_equal 4, issue.fixed_version_id
2393 2404 assert_not_equal issue.project_id, issue.fixed_version.project_id
2394 2405 end
2395 2406
2396 2407 def test_put_update_should_redirect_back_using_the_back_url_parameter
2397 2408 issue = Issue.find(2)
2398 2409 @request.session[:user_id] = 2
2399 2410
2400 2411 put :update,
2401 2412 :id => issue.id,
2402 2413 :issue => {
2403 2414 :fixed_version_id => 4
2404 2415 },
2405 2416 :back_url => '/issues'
2406 2417
2407 2418 assert_response :redirect
2408 2419 assert_redirected_to '/issues'
2409 2420 end
2410 2421
2411 2422 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
2412 2423 issue = Issue.find(2)
2413 2424 @request.session[:user_id] = 2
2414 2425
2415 2426 put :update,
2416 2427 :id => issue.id,
2417 2428 :issue => {
2418 2429 :fixed_version_id => 4
2419 2430 },
2420 2431 :back_url => 'http://google.com'
2421 2432
2422 2433 assert_response :redirect
2423 2434 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
2424 2435 end
2425 2436
2426 2437 def test_get_bulk_edit
2427 2438 @request.session[:user_id] = 2
2428 2439 get :bulk_edit, :ids => [1, 2]
2429 2440 assert_response :success
2430 2441 assert_template 'bulk_edit'
2431 2442
2432 2443 assert_tag :select, :attributes => {:name => 'issue[project_id]'}
2433 2444 assert_tag :input, :attributes => {:name => 'issue[parent_issue_id]'}
2434 2445
2435 2446 # Project specific custom field, date type
2436 2447 field = CustomField.find(9)
2437 2448 assert !field.is_for_all?
2438 2449 assert_equal 'date', field.field_format
2439 2450 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
2440 2451
2441 2452 # System wide custom field
2442 2453 assert CustomField.find(1).is_for_all?
2443 2454 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
2444 2455
2445 2456 # Be sure we don't display inactive IssuePriorities
2446 2457 assert ! IssuePriority.find(15).active?
2447 2458 assert_no_tag :option, :attributes => {:value => '15'},
2448 2459 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
2449 2460 end
2450 2461
2451 2462 def test_get_bulk_edit_on_different_projects
2452 2463 @request.session[:user_id] = 2
2453 2464 get :bulk_edit, :ids => [1, 2, 6]
2454 2465 assert_response :success
2455 2466 assert_template 'bulk_edit'
2456 2467
2457 2468 # Can not set issues from different projects as children of an issue
2458 2469 assert_no_tag :input, :attributes => {:name => 'issue[parent_issue_id]'}
2459 2470
2460 2471 # Project specific custom field, date type
2461 2472 field = CustomField.find(9)
2462 2473 assert !field.is_for_all?
2463 2474 assert !field.project_ids.include?(Issue.find(6).project_id)
2464 2475 assert_no_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
2465 2476 end
2466 2477
2467 2478 def test_get_bulk_edit_with_user_custom_field
2468 2479 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true)
2469 2480
2470 2481 @request.session[:user_id] = 2
2471 2482 get :bulk_edit, :ids => [1, 2]
2472 2483 assert_response :success
2473 2484 assert_template 'bulk_edit'
2474 2485
2475 2486 assert_tag :select,
2476 2487 :attributes => {:name => "issue[custom_field_values][#{field.id}]"},
2477 2488 :children => {
2478 2489 :only => {:tag => 'option'},
2479 2490 :count => Project.find(1).users.count + 1
2480 2491 }
2481 2492 end
2482 2493
2483 2494 def test_get_bulk_edit_with_version_custom_field
2484 2495 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true)
2485 2496
2486 2497 @request.session[:user_id] = 2
2487 2498 get :bulk_edit, :ids => [1, 2]
2488 2499 assert_response :success
2489 2500 assert_template 'bulk_edit'
2490 2501
2491 2502 assert_tag :select,
2492 2503 :attributes => {:name => "issue[custom_field_values][#{field.id}]"},
2493 2504 :children => {
2494 2505 :only => {:tag => 'option'},
2495 2506 :count => Project.find(1).shared_versions.count + 1
2496 2507 }
2497 2508 end
2498 2509
2499 2510 def test_get_bulk_edit_with_multi_custom_field
2500 2511 field = CustomField.find(1)
2501 2512 field.update_attribute :multiple, true
2502 2513
2503 2514 @request.session[:user_id] = 2
2504 2515 get :bulk_edit, :ids => [1, 2]
2505 2516 assert_response :success
2506 2517 assert_template 'bulk_edit'
2507 2518
2508 2519 assert_tag :select,
2509 2520 :attributes => {:name => "issue[custom_field_values][1][]"},
2510 2521 :children => {
2511 2522 :only => {:tag => 'option'},
2512 2523 :count => 3
2513 2524 }
2514 2525 end
2515 2526
2516 2527 def test_bulk_update
2517 2528 @request.session[:user_id] = 2
2518 2529 # update issues priority
2519 2530 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
2520 2531 :issue => {:priority_id => 7,
2521 2532 :assigned_to_id => '',
2522 2533 :custom_field_values => {'2' => ''}}
2523 2534
2524 2535 assert_response 302
2525 2536 # check that the issues were updated
2526 2537 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
2527 2538
2528 2539 issue = Issue.find(1)
2529 2540 journal = issue.journals.find(:first, :order => 'created_on DESC')
2530 2541 assert_equal '125', issue.custom_value_for(2).value
2531 2542 assert_equal 'Bulk editing', journal.notes
2532 2543 assert_equal 1, journal.details.size
2533 2544 end
2534 2545
2535 2546 def test_bulk_update_with_group_assignee
2536 2547 group = Group.find(11)
2537 2548 project = Project.find(1)
2538 2549 project.members << Member.new(:principal => group, :roles => [Role.first])
2539 2550
2540 2551 @request.session[:user_id] = 2
2541 2552 # update issues assignee
2542 2553 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
2543 2554 :issue => {:priority_id => '',
2544 2555 :assigned_to_id => group.id,
2545 2556 :custom_field_values => {'2' => ''}}
2546 2557
2547 2558 assert_response 302
2548 2559 assert_equal [group, group], Issue.find_all_by_id([1, 2]).collect {|i| i.assigned_to}
2549 2560 end
2550 2561
2551 2562 def test_bulk_update_on_different_projects
2552 2563 @request.session[:user_id] = 2
2553 2564 # update issues priority
2554 2565 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
2555 2566 :issue => {:priority_id => 7,
2556 2567 :assigned_to_id => '',
2557 2568 :custom_field_values => {'2' => ''}}
2558 2569
2559 2570 assert_response 302
2560 2571 # check that the issues were updated
2561 2572 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
2562 2573
2563 2574 issue = Issue.find(1)
2564 2575 journal = issue.journals.find(:first, :order => 'created_on DESC')
2565 2576 assert_equal '125', issue.custom_value_for(2).value
2566 2577 assert_equal 'Bulk editing', journal.notes
2567 2578 assert_equal 1, journal.details.size
2568 2579 end
2569 2580
2570 2581 def test_bulk_update_on_different_projects_without_rights
2571 2582 @request.session[:user_id] = 3
2572 2583 user = User.find(3)
2573 2584 action = { :controller => "issues", :action => "bulk_update" }
2574 2585 assert user.allowed_to?(action, Issue.find(1).project)
2575 2586 assert ! user.allowed_to?(action, Issue.find(6).project)
2576 2587 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
2577 2588 :issue => {:priority_id => 7,
2578 2589 :assigned_to_id => '',
2579 2590 :custom_field_values => {'2' => ''}}
2580 2591 assert_response 403
2581 2592 assert_not_equal "Bulk should fail", Journal.last.notes
2582 2593 end
2583 2594
2584 2595 def test_bullk_update_should_send_a_notification
2585 2596 @request.session[:user_id] = 2
2586 2597 ActionMailer::Base.deliveries.clear
2587 2598 post(:bulk_update,
2588 2599 {
2589 2600 :ids => [1, 2],
2590 2601 :notes => 'Bulk editing',
2591 2602 :issue => {
2592 2603 :priority_id => 7,
2593 2604 :assigned_to_id => '',
2594 2605 :custom_field_values => {'2' => ''}
2595 2606 }
2596 2607 })
2597 2608
2598 2609 assert_response 302
2599 2610 assert_equal 2, ActionMailer::Base.deliveries.size
2600 2611 end
2601 2612
2602 2613 def test_bulk_update_project
2603 2614 @request.session[:user_id] = 2
2604 2615 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
2605 2616 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2606 2617 # Issues moved to project 2
2607 2618 assert_equal 2, Issue.find(1).project_id
2608 2619 assert_equal 2, Issue.find(2).project_id
2609 2620 # No tracker change
2610 2621 assert_equal 1, Issue.find(1).tracker_id
2611 2622 assert_equal 2, Issue.find(2).tracker_id
2612 2623 end
2613 2624
2614 2625 def test_bulk_update_project_on_single_issue_should_follow_when_needed
2615 2626 @request.session[:user_id] = 2
2616 2627 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
2617 2628 assert_redirected_to '/issues/1'
2618 2629 end
2619 2630
2620 2631 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
2621 2632 @request.session[:user_id] = 2
2622 2633 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
2623 2634 assert_redirected_to '/projects/onlinestore/issues'
2624 2635 end
2625 2636
2626 2637 def test_bulk_update_tracker
2627 2638 @request.session[:user_id] = 2
2628 2639 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
2629 2640 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2630 2641 assert_equal 2, Issue.find(1).tracker_id
2631 2642 assert_equal 2, Issue.find(2).tracker_id
2632 2643 end
2633 2644
2634 2645 def test_bulk_update_status
2635 2646 @request.session[:user_id] = 2
2636 2647 # update issues priority
2637 2648 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
2638 2649 :issue => {:priority_id => '',
2639 2650 :assigned_to_id => '',
2640 2651 :status_id => '5'}
2641 2652
2642 2653 assert_response 302
2643 2654 issue = Issue.find(1)
2644 2655 assert issue.closed?
2645 2656 end
2646 2657
2647 2658 def test_bulk_update_priority
2648 2659 @request.session[:user_id] = 2
2649 2660 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
2650 2661
2651 2662 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2652 2663 assert_equal 6, Issue.find(1).priority_id
2653 2664 assert_equal 6, Issue.find(2).priority_id
2654 2665 end
2655 2666
2656 2667 def test_bulk_update_with_notes
2657 2668 @request.session[:user_id] = 2
2658 2669 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
2659 2670
2660 2671 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2661 2672 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
2662 2673 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
2663 2674 end
2664 2675
2665 2676 def test_bulk_update_parent_id
2666 2677 @request.session[:user_id] = 2
2667 2678 post :bulk_update, :ids => [1, 3],
2668 2679 :notes => 'Bulk editing parent',
2669 2680 :issue => {:priority_id => '', :assigned_to_id => '', :status_id => '', :parent_issue_id => '2'}
2670 2681
2671 2682 assert_response 302
2672 2683 parent = Issue.find(2)
2673 2684 assert_equal parent.id, Issue.find(1).parent_id
2674 2685 assert_equal parent.id, Issue.find(3).parent_id
2675 2686 assert_equal [1, 3], parent.children.collect(&:id).sort
2676 2687 end
2677 2688
2678 2689 def test_bulk_update_custom_field
2679 2690 @request.session[:user_id] = 2
2680 2691 # update issues priority
2681 2692 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
2682 2693 :issue => {:priority_id => '',
2683 2694 :assigned_to_id => '',
2684 2695 :custom_field_values => {'2' => '777'}}
2685 2696
2686 2697 assert_response 302
2687 2698
2688 2699 issue = Issue.find(1)
2689 2700 journal = issue.journals.find(:first, :order => 'created_on DESC')
2690 2701 assert_equal '777', issue.custom_value_for(2).value
2691 2702 assert_equal 1, journal.details.size
2692 2703 assert_equal '125', journal.details.first.old_value
2693 2704 assert_equal '777', journal.details.first.value
2694 2705 end
2695 2706
2696 2707 def test_bulk_update_multi_custom_field
2697 2708 field = CustomField.find(1)
2698 2709 field.update_attribute :multiple, true
2699 2710
2700 2711 @request.session[:user_id] = 2
2701 2712 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
2702 2713 :issue => {:priority_id => '',
2703 2714 :assigned_to_id => '',
2704 2715 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
2705 2716
2706 2717 assert_response 302
2707 2718
2708 2719 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
2709 2720 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
2710 2721 # the custom field is not associated with the issue tracker
2711 2722 assert_nil Issue.find(2).custom_field_value(1)
2712 2723 end
2713 2724
2714 2725 def test_bulk_update_unassign
2715 2726 assert_not_nil Issue.find(2).assigned_to
2716 2727 @request.session[:user_id] = 2
2717 2728 # unassign issues
2718 2729 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
2719 2730 assert_response 302
2720 2731 # check that the issues were updated
2721 2732 assert_nil Issue.find(2).assigned_to
2722 2733 end
2723 2734
2724 2735 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
2725 2736 @request.session[:user_id] = 2
2726 2737
2727 2738 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
2728 2739
2729 2740 assert_response :redirect
2730 2741 issues = Issue.find([1,2])
2731 2742 issues.each do |issue|
2732 2743 assert_equal 4, issue.fixed_version_id
2733 2744 assert_not_equal issue.project_id, issue.fixed_version.project_id
2734 2745 end
2735 2746 end
2736 2747
2737 2748 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
2738 2749 @request.session[:user_id] = 2
2739 2750 post :bulk_update, :ids => [1,2], :back_url => '/issues'
2740 2751
2741 2752 assert_response :redirect
2742 2753 assert_redirected_to '/issues'
2743 2754 end
2744 2755
2745 2756 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
2746 2757 @request.session[:user_id] = 2
2747 2758 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
2748 2759
2749 2760 assert_response :redirect
2750 2761 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
2751 2762 end
2752 2763
2753 2764 def test_bulk_copy_to_another_project
2754 2765 @request.session[:user_id] = 2
2755 2766 assert_difference 'Issue.count', 2 do
2756 2767 assert_no_difference 'Project.find(1).issues.count' do
2757 2768 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
2758 2769 end
2759 2770 end
2760 2771 assert_redirected_to '/projects/ecookbook/issues'
2761 2772 end
2762 2773
2763 2774 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
2764 2775 @request.session[:user_id] = 2
2765 2776 issue_before_move = Issue.find(1)
2766 2777 assert_difference 'Issue.count', 1 do
2767 2778 assert_no_difference 'Project.find(1).issues.count' do
2768 2779 post :bulk_update, :ids => [1], :copy => '1',
2769 2780 :issue => {
2770 2781 :project_id => '2', :tracker_id => '', :assigned_to_id => '',
2771 2782 :status_id => '', :start_date => '', :due_date => ''
2772 2783 }
2773 2784 end
2774 2785 end
2775 2786 issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2})
2776 2787 assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id
2777 2788 assert_equal issue_before_move.status_id, issue_after_move.status_id
2778 2789 assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id
2779 2790 end
2780 2791
2781 2792 def test_bulk_copy_should_allow_changing_the_issue_attributes
2782 2793 # Fixes random test failure with Mysql
2783 2794 # where Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
2784 2795 # doesn't return the expected results
2785 2796 Issue.delete_all("project_id=2")
2786 2797
2787 2798 @request.session[:user_id] = 2
2788 2799 assert_difference 'Issue.count', 2 do
2789 2800 assert_no_difference 'Project.find(1).issues.count' do
2790 2801 post :bulk_update, :ids => [1, 2], :copy => '1',
2791 2802 :issue => {
2792 2803 :project_id => '2', :tracker_id => '', :assigned_to_id => '4',
2793 2804 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
2794 2805 }
2795 2806 end
2796 2807 end
2797 2808
2798 2809 copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
2799 2810 assert_equal 2, copied_issues.size
2800 2811 copied_issues.each do |issue|
2801 2812 assert_equal 2, issue.project_id, "Project is incorrect"
2802 2813 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
2803 2814 assert_equal 3, issue.status_id, "Status is incorrect"
2804 2815 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
2805 2816 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
2806 2817 end
2807 2818 end
2808 2819
2809 2820 def test_bulk_copy_should_allow_adding_a_note
2810 2821 @request.session[:user_id] = 2
2811 2822 assert_difference 'Issue.count', 1 do
2812 2823 post :bulk_update, :ids => [1], :copy => '1',
2813 2824 :notes => 'Copying one issue',
2814 2825 :issue => {
2815 2826 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
2816 2827 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
2817 2828 }
2818 2829 end
2819 2830
2820 2831 issue = Issue.first(:order => 'id DESC')
2821 2832 assert_equal 1, issue.journals.size
2822 2833 journal = issue.journals.first
2823 2834 assert_equal 0, journal.details.size
2824 2835 assert_equal 'Copying one issue', journal.notes
2825 2836 end
2826 2837
2827 2838 def test_bulk_copy_to_another_project_should_follow_when_needed
2828 2839 @request.session[:user_id] = 2
2829 2840 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
2830 2841 issue = Issue.first(:order => 'id DESC')
2831 2842 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
2832 2843 end
2833 2844
2834 2845 def test_destroy_issue_with_no_time_entries
2835 2846 assert_nil TimeEntry.find_by_issue_id(2)
2836 2847 @request.session[:user_id] = 2
2837 2848
2838 2849 assert_difference 'Issue.count', -1 do
2839 2850 delete :destroy, :id => 2
2840 2851 end
2841 2852 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
2842 2853 assert_nil Issue.find_by_id(2)
2843 2854 end
2844 2855
2845 2856 def test_destroy_issues_with_time_entries
2846 2857 @request.session[:user_id] = 2
2847 2858
2848 2859 assert_no_difference 'Issue.count' do
2849 2860 delete :destroy, :ids => [1, 3]
2850 2861 end
2851 2862 assert_response :success
2852 2863 assert_template 'destroy'
2853 2864 assert_not_nil assigns(:hours)
2854 2865 assert Issue.find_by_id(1) && Issue.find_by_id(3)
2855 2866 assert_tag 'form',
2856 2867 :descendant => {:tag => 'input', :attributes => {:name => '_method', :value => 'delete'}}
2857 2868 end
2858 2869
2859 2870 def test_destroy_issues_and_destroy_time_entries
2860 2871 @request.session[:user_id] = 2
2861 2872
2862 2873 assert_difference 'Issue.count', -2 do
2863 2874 assert_difference 'TimeEntry.count', -3 do
2864 2875 delete :destroy, :ids => [1, 3], :todo => 'destroy'
2865 2876 end
2866 2877 end
2867 2878 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
2868 2879 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
2869 2880 assert_nil TimeEntry.find_by_id([1, 2])
2870 2881 end
2871 2882
2872 2883 def test_destroy_issues_and_assign_time_entries_to_project
2873 2884 @request.session[:user_id] = 2
2874 2885
2875 2886 assert_difference 'Issue.count', -2 do
2876 2887 assert_no_difference 'TimeEntry.count' do
2877 2888 delete :destroy, :ids => [1, 3], :todo => 'nullify'
2878 2889 end
2879 2890 end
2880 2891 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
2881 2892 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
2882 2893 assert_nil TimeEntry.find(1).issue_id
2883 2894 assert_nil TimeEntry.find(2).issue_id
2884 2895 end
2885 2896
2886 2897 def test_destroy_issues_and_reassign_time_entries_to_another_issue
2887 2898 @request.session[:user_id] = 2
2888 2899
2889 2900 assert_difference 'Issue.count', -2 do
2890 2901 assert_no_difference 'TimeEntry.count' do
2891 2902 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
2892 2903 end
2893 2904 end
2894 2905 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
2895 2906 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
2896 2907 assert_equal 2, TimeEntry.find(1).issue_id
2897 2908 assert_equal 2, TimeEntry.find(2).issue_id
2898 2909 end
2899 2910
2900 2911 def test_destroy_issues_from_different_projects
2901 2912 @request.session[:user_id] = 2
2902 2913
2903 2914 assert_difference 'Issue.count', -3 do
2904 2915 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
2905 2916 end
2906 2917 assert_redirected_to :controller => 'issues', :action => 'index'
2907 2918 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
2908 2919 end
2909 2920
2910 2921 def test_destroy_parent_and_child_issues
2911 2922 parent = Issue.generate!(:project_id => 1, :tracker_id => 1)
2912 2923 child = Issue.generate!(:project_id => 1, :tracker_id => 1, :parent_issue_id => parent.id)
2913 2924 assert child.is_descendant_of?(parent.reload)
2914 2925
2915 2926 @request.session[:user_id] = 2
2916 2927 assert_difference 'Issue.count', -2 do
2917 2928 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
2918 2929 end
2919 2930 assert_response 302
2920 2931 end
2921 2932
2922 2933 def test_default_search_scope
2923 2934 get :index
2924 2935 assert_tag :div, :attributes => {:id => 'quick-search'},
2925 2936 :child => {:tag => 'form',
2926 2937 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
2927 2938 end
2928 2939 end
General Comments 0
You need to be logged in to leave comments. Login now