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