##// END OF EJS Templates
Merged r15608 (#23206)....
Jean-Philippe Lang -
r15230:723857fc4281
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_relations
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,4771 +1,4782
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, :user_preferences,
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_include status, header
604 615 issue_line = lines.find {|l| l =~ /^#{issue.id},/}
605 616 assert_include str_big5, issue_line
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_index_should_include_new_issue_link
1077 1088 @request.session[:user_id] = 2
1078 1089 get :index, :project_id => 1
1079 1090 assert_select '#content a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
1080 1091 end
1081 1092
1082 1093 def test_index_should_not_include_new_issue_link_for_project_without_trackers
1083 1094 Project.find(1).trackers.clear
1084 1095
1085 1096 @request.session[:user_id] = 2
1086 1097 get :index, :project_id => 1
1087 1098 assert_select '#content a.new-issue', 0
1088 1099 end
1089 1100
1090 1101 def test_index_should_not_include_new_issue_link_for_users_with_copy_issues_permission_only
1091 1102 role = Role.find(1)
1092 1103 role.remove_permission! :add_issues
1093 1104 role.add_permission! :copy_issues
1094 1105
1095 1106 @request.session[:user_id] = 2
1096 1107 get :index, :project_id => 1
1097 1108 assert_select '#content a.new-issue', 0
1098 1109 end
1099 1110
1100 1111 def test_index_without_project_should_include_new_issue_link
1101 1112 @request.session[:user_id] = 2
1102 1113 get :index
1103 1114 assert_select '#content a.new-issue[href="/issues/new"]', :text => 'New issue'
1104 1115 end
1105 1116
1106 1117 def test_index_should_not_include_new_issue_tab_when_disabled
1107 1118 with_settings :new_item_menu_tab => '0' do
1108 1119 @request.session[:user_id] = 2
1109 1120 get :index, :project_id => 1
1110 1121 assert_select '#main-menu a.new-issue', 0
1111 1122 end
1112 1123 end
1113 1124
1114 1125 def test_index_should_include_new_issue_tab_when_enabled
1115 1126 with_settings :new_item_menu_tab => '1' do
1116 1127 @request.session[:user_id] = 2
1117 1128 get :index, :project_id => 1
1118 1129 assert_select '#main-menu a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
1119 1130 end
1120 1131 end
1121 1132
1122 1133 def test_new_should_have_new_issue_tab_as_current_menu_item
1123 1134 with_settings :new_item_menu_tab => '1' do
1124 1135 @request.session[:user_id] = 2
1125 1136 get :new, :project_id => 1
1126 1137 assert_select '#main-menu a.new-issue.selected'
1127 1138 end
1128 1139 end
1129 1140
1130 1141 def test_index_should_not_include_new_issue_tab_for_project_without_trackers
1131 1142 with_settings :new_item_menu_tab => '1' do
1132 1143 Project.find(1).trackers.clear
1133 1144
1134 1145 @request.session[:user_id] = 2
1135 1146 get :index, :project_id => 1
1136 1147 assert_select '#main-menu a.new-issue', 0
1137 1148 end
1138 1149 end
1139 1150
1140 1151 def test_index_should_not_include_new_issue_tab_for_users_with_copy_issues_permission_only
1141 1152 with_settings :new_item_menu_tab => '1' do
1142 1153 role = Role.find(1)
1143 1154 role.remove_permission! :add_issues
1144 1155 role.add_permission! :copy_issues
1145 1156
1146 1157 @request.session[:user_id] = 2
1147 1158 get :index, :project_id => 1
1148 1159 assert_select '#main-menu a.new-issue', 0
1149 1160 end
1150 1161 end
1151 1162
1152 1163 def test_show_by_anonymous
1153 1164 get :show, :id => 1
1154 1165 assert_response :success
1155 1166 assert_template 'show'
1156 1167 assert_equal Issue.find(1), assigns(:issue)
1157 1168 assert_select 'div.issue div.description', :text => /Unable to print recipes/
1158 1169 # anonymous role is allowed to add a note
1159 1170 assert_select 'form#issue-form' do
1160 1171 assert_select 'fieldset' do
1161 1172 assert_select 'legend', :text => 'Notes'
1162 1173 assert_select 'textarea[name=?]', 'issue[notes]'
1163 1174 end
1164 1175 end
1165 1176 assert_select 'title', :text => "Bug #1: Cannot print recipes - eCookbook - Redmine"
1166 1177 end
1167 1178
1168 1179 def test_show_by_manager
1169 1180 @request.session[:user_id] = 2
1170 1181 get :show, :id => 1
1171 1182 assert_response :success
1172 1183 assert_select 'a', :text => /Quote/
1173 1184 assert_select 'form#issue-form' do
1174 1185 assert_select 'fieldset' do
1175 1186 assert_select 'legend', :text => 'Change properties'
1176 1187 assert_select 'input[name=?]', 'issue[subject]'
1177 1188 end
1178 1189 assert_select 'fieldset' do
1179 1190 assert_select 'legend', :text => 'Log time'
1180 1191 assert_select 'input[name=?]', 'time_entry[hours]'
1181 1192 end
1182 1193 assert_select 'fieldset' do
1183 1194 assert_select 'legend', :text => 'Notes'
1184 1195 assert_select 'textarea[name=?]', 'issue[notes]'
1185 1196 end
1186 1197 end
1187 1198 end
1188 1199
1189 1200 def test_show_should_display_update_form
1190 1201 @request.session[:user_id] = 2
1191 1202 get :show, :id => 1
1192 1203 assert_response :success
1193 1204
1194 1205 assert_select 'form#issue-form' do
1195 1206 assert_select 'input[name=?]', 'issue[is_private]'
1196 1207 assert_select 'select[name=?]', 'issue[project_id]'
1197 1208 assert_select 'select[name=?]', 'issue[tracker_id]'
1198 1209 assert_select 'input[name=?]', 'issue[subject]'
1199 1210 assert_select 'textarea[name=?]', 'issue[description]'
1200 1211 assert_select 'select[name=?]', 'issue[status_id]'
1201 1212 assert_select 'select[name=?]', 'issue[priority_id]'
1202 1213 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1203 1214 assert_select 'select[name=?]', 'issue[category_id]'
1204 1215 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1205 1216 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1206 1217 assert_select 'input[name=?]', 'issue[start_date]'
1207 1218 assert_select 'input[name=?]', 'issue[due_date]'
1208 1219 assert_select 'select[name=?]', 'issue[done_ratio]'
1209 1220 assert_select 'input[name=?]', 'issue[custom_field_values][2]'
1210 1221 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1211 1222 assert_select 'textarea[name=?]', 'issue[notes]'
1212 1223 end
1213 1224 end
1214 1225
1215 1226 def test_show_should_display_update_form_with_minimal_permissions
1216 1227 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
1217 1228 WorkflowTransition.delete_all :role_id => 1
1218 1229
1219 1230 @request.session[:user_id] = 2
1220 1231 get :show, :id => 1
1221 1232 assert_response :success
1222 1233
1223 1234 assert_select 'form#issue-form' do
1224 1235 assert_select 'input[name=?]', 'issue[is_private]', 0
1225 1236 assert_select 'select[name=?]', 'issue[project_id]', 0
1226 1237 assert_select 'select[name=?]', 'issue[tracker_id]', 0
1227 1238 assert_select 'input[name=?]', 'issue[subject]', 0
1228 1239 assert_select 'textarea[name=?]', 'issue[description]', 0
1229 1240 assert_select 'select[name=?]', 'issue[status_id]', 0
1230 1241 assert_select 'select[name=?]', 'issue[priority_id]', 0
1231 1242 assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
1232 1243 assert_select 'select[name=?]', 'issue[category_id]', 0
1233 1244 assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
1234 1245 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1235 1246 assert_select 'input[name=?]', 'issue[start_date]', 0
1236 1247 assert_select 'input[name=?]', 'issue[due_date]', 0
1237 1248 assert_select 'select[name=?]', 'issue[done_ratio]', 0
1238 1249 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
1239 1250 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1240 1251 assert_select 'textarea[name=?]', 'issue[notes]'
1241 1252 end
1242 1253 end
1243 1254
1244 1255 def test_show_should_not_display_update_form_without_permissions
1245 1256 Role.find(1).update_attribute :permissions, [:view_issues]
1246 1257
1247 1258 @request.session[:user_id] = 2
1248 1259 get :show, :id => 1
1249 1260 assert_response :success
1250 1261
1251 1262 assert_select 'form#issue-form', 0
1252 1263 end
1253 1264
1254 1265 def test_update_form_should_not_display_inactive_enumerations
1255 1266 assert !IssuePriority.find(15).active?
1256 1267
1257 1268 @request.session[:user_id] = 2
1258 1269 get :show, :id => 1
1259 1270 assert_response :success
1260 1271
1261 1272 assert_select 'form#issue-form' do
1262 1273 assert_select 'select[name=?]', 'issue[priority_id]' do
1263 1274 assert_select 'option[value="4"]'
1264 1275 assert_select 'option[value="15"]', 0
1265 1276 end
1266 1277 end
1267 1278 end
1268 1279
1269 1280 def test_update_form_should_allow_attachment_upload
1270 1281 @request.session[:user_id] = 2
1271 1282 get :show, :id => 1
1272 1283
1273 1284 assert_select 'form#issue-form[method=post][enctype="multipart/form-data"]' do
1274 1285 assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
1275 1286 end
1276 1287 end
1277 1288
1278 1289 def test_show_should_deny_anonymous_access_without_permission
1279 1290 Role.anonymous.remove_permission!(:view_issues)
1280 1291 get :show, :id => 1
1281 1292 assert_response :redirect
1282 1293 end
1283 1294
1284 1295 def test_show_should_deny_anonymous_access_to_private_issue
1285 1296 Issue.where(:id => 1).update_all(["is_private = ?", true])
1286 1297 get :show, :id => 1
1287 1298 assert_response :redirect
1288 1299 end
1289 1300
1290 1301 def test_show_should_deny_non_member_access_without_permission
1291 1302 Role.non_member.remove_permission!(:view_issues)
1292 1303 @request.session[:user_id] = 9
1293 1304 get :show, :id => 1
1294 1305 assert_response 403
1295 1306 end
1296 1307
1297 1308 def test_show_should_deny_non_member_access_to_private_issue
1298 1309 Issue.where(:id => 1).update_all(["is_private = ?", true])
1299 1310 @request.session[:user_id] = 9
1300 1311 get :show, :id => 1
1301 1312 assert_response 403
1302 1313 end
1303 1314
1304 1315 def test_show_should_deny_member_access_without_permission
1305 1316 Role.find(1).remove_permission!(:view_issues)
1306 1317 @request.session[:user_id] = 2
1307 1318 get :show, :id => 1
1308 1319 assert_response 403
1309 1320 end
1310 1321
1311 1322 def test_show_should_deny_member_access_to_private_issue_without_permission
1312 1323 Issue.where(:id => 1).update_all(["is_private = ?", true])
1313 1324 @request.session[:user_id] = 3
1314 1325 get :show, :id => 1
1315 1326 assert_response 403
1316 1327 end
1317 1328
1318 1329 def test_show_should_allow_author_access_to_private_issue
1319 1330 Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
1320 1331 @request.session[:user_id] = 3
1321 1332 get :show, :id => 1
1322 1333 assert_response :success
1323 1334 end
1324 1335
1325 1336 def test_show_should_allow_assignee_access_to_private_issue
1326 1337 Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
1327 1338 @request.session[:user_id] = 3
1328 1339 get :show, :id => 1
1329 1340 assert_response :success
1330 1341 end
1331 1342
1332 1343 def test_show_should_allow_member_access_to_private_issue_with_permission
1333 1344 Issue.where(:id => 1).update_all(["is_private = ?", true])
1334 1345 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
1335 1346 @request.session[:user_id] = 3
1336 1347 get :show, :id => 1
1337 1348 assert_response :success
1338 1349 end
1339 1350
1340 1351 def test_show_should_not_disclose_relations_to_invisible_issues
1341 1352 Setting.cross_project_issue_relations = '1'
1342 1353 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
1343 1354 # Relation to a private project issue
1344 1355 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
1345 1356
1346 1357 get :show, :id => 1
1347 1358 assert_response :success
1348 1359
1349 1360 assert_select 'div#relations' do
1350 1361 assert_select 'a', :text => /#2$/
1351 1362 assert_select 'a', :text => /#4$/, :count => 0
1352 1363 end
1353 1364 end
1354 1365
1355 1366 def test_show_should_list_subtasks
1356 1367 Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1357 1368
1358 1369 get :show, :id => 1
1359 1370 assert_response :success
1360 1371
1361 1372 assert_select 'div#issue_tree' do
1362 1373 assert_select 'td.subject', :text => /Child Issue/
1363 1374 end
1364 1375 end
1365 1376
1366 1377 def test_show_should_list_parents
1367 1378 issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1368 1379
1369 1380 get :show, :id => issue.id
1370 1381 assert_response :success
1371 1382
1372 1383 assert_select 'div.subject' do
1373 1384 assert_select 'h3', 'Child Issue'
1374 1385 assert_select 'a[href="/issues/1"]'
1375 1386 end
1376 1387 end
1377 1388
1378 1389 def test_show_should_not_display_prev_next_links_without_query_in_session
1379 1390 get :show, :id => 1
1380 1391 assert_response :success
1381 1392 assert_nil assigns(:prev_issue_id)
1382 1393 assert_nil assigns(:next_issue_id)
1383 1394
1384 1395 assert_select 'div.next-prev-links', 0
1385 1396 end
1386 1397
1387 1398 def test_show_should_display_prev_next_links_with_query_in_session
1388 1399 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1389 1400 @request.session['issues_index_sort'] = 'id'
1390 1401
1391 1402 with_settings :display_subprojects_issues => '0' do
1392 1403 get :show, :id => 3
1393 1404 end
1394 1405
1395 1406 assert_response :success
1396 1407 # Previous and next issues for all projects
1397 1408 assert_equal 2, assigns(:prev_issue_id)
1398 1409 assert_equal 5, assigns(:next_issue_id)
1399 1410
1400 1411 count = Issue.open.visible.count
1401 1412
1402 1413 assert_select 'div.next-prev-links' do
1403 1414 assert_select 'a[href="/issues/2"]', :text => /Previous/
1404 1415 assert_select 'a[href="/issues/5"]', :text => /Next/
1405 1416 assert_select 'span.position', :text => "3 of #{count}"
1406 1417 end
1407 1418 end
1408 1419
1409 1420 def test_show_should_display_prev_next_links_with_saved_query_in_session
1410 1421 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1,
1411 1422 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1412 1423 :sort_criteria => [['id', 'asc']])
1413 1424 @request.session[:query] = {:id => query.id, :project_id => nil}
1414 1425
1415 1426 get :show, :id => 11
1416 1427
1417 1428 assert_response :success
1418 1429 assert_equal query, assigns(:query)
1419 1430 # Previous and next issues for all projects
1420 1431 assert_equal 8, assigns(:prev_issue_id)
1421 1432 assert_equal 12, assigns(:next_issue_id)
1422 1433
1423 1434 assert_select 'div.next-prev-links' do
1424 1435 assert_select 'a[href="/issues/8"]', :text => /Previous/
1425 1436 assert_select 'a[href="/issues/12"]', :text => /Next/
1426 1437 end
1427 1438 end
1428 1439
1429 1440 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1430 1441 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1431 1442
1432 1443 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1433 1444 @request.session['issues_index_sort'] = assoc_sort
1434 1445
1435 1446 get :show, :id => 3
1436 1447 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1437 1448
1438 1449 assert_select 'div.next-prev-links' do
1439 1450 assert_select 'a', :text => /(Previous|Next)/
1440 1451 end
1441 1452 end
1442 1453 end
1443 1454
1444 1455 def test_show_should_display_prev_next_links_with_project_query_in_session
1445 1456 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1446 1457 @request.session['issues_index_sort'] = 'id'
1447 1458
1448 1459 with_settings :display_subprojects_issues => '0' do
1449 1460 get :show, :id => 3
1450 1461 end
1451 1462
1452 1463 assert_response :success
1453 1464 # Previous and next issues inside project
1454 1465 assert_equal 2, assigns(:prev_issue_id)
1455 1466 assert_equal 7, assigns(:next_issue_id)
1456 1467
1457 1468 assert_select 'div.next-prev-links' do
1458 1469 assert_select 'a[href="/issues/2"]', :text => /Previous/
1459 1470 assert_select 'a[href="/issues/7"]', :text => /Next/
1460 1471 end
1461 1472 end
1462 1473
1463 1474 def test_show_should_not_display_prev_link_for_first_issue
1464 1475 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1465 1476 @request.session['issues_index_sort'] = 'id'
1466 1477
1467 1478 with_settings :display_subprojects_issues => '0' do
1468 1479 get :show, :id => 1
1469 1480 end
1470 1481
1471 1482 assert_response :success
1472 1483 assert_nil assigns(:prev_issue_id)
1473 1484 assert_equal 2, assigns(:next_issue_id)
1474 1485
1475 1486 assert_select 'div.next-prev-links' do
1476 1487 assert_select 'a', :text => /Previous/, :count => 0
1477 1488 assert_select 'a[href="/issues/2"]', :text => /Next/
1478 1489 end
1479 1490 end
1480 1491
1481 1492 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1482 1493 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1483 1494 @request.session['issues_index_sort'] = 'id'
1484 1495
1485 1496 get :show, :id => 1
1486 1497
1487 1498 assert_response :success
1488 1499 assert_nil assigns(:prev_issue_id)
1489 1500 assert_nil assigns(:next_issue_id)
1490 1501
1491 1502 assert_select 'a', :text => /Previous/, :count => 0
1492 1503 assert_select 'a', :text => /Next/, :count => 0
1493 1504 end
1494 1505
1495 1506 def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
1496 1507 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
1497 1508 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
1498 1509 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
1499 1510 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
1500 1511 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
1501 1512
1502 1513 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1, :filters => {},
1503 1514 :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
1504 1515 @request.session[:query] = {:id => query.id, :project_id => nil}
1505 1516
1506 1517 get :show, :id => 3
1507 1518 assert_response :success
1508 1519
1509 1520 assert_equal 2, assigns(:prev_issue_id)
1510 1521 assert_equal 1, assigns(:next_issue_id)
1511 1522
1512 1523 assert_select 'div.next-prev-links' do
1513 1524 assert_select 'a[href="/issues/2"]', :text => /Previous/
1514 1525 assert_select 'a[href="/issues/1"]', :text => /Next/
1515 1526 end
1516 1527 end
1517 1528
1518 1529 def test_show_should_display_prev_next_links_when_request_has_previous_and_next_issue_ids_params
1519 1530 get :show, :id => 1, :prev_issue_id => 1, :next_issue_id => 3, :issue_position => 2, :issue_count => 4
1520 1531 assert_response :success
1521 1532
1522 1533 assert_select 'div.next-prev-links' do
1523 1534 assert_select 'a[href="/issues/1"]', :text => /Previous/
1524 1535 assert_select 'a[href="/issues/3"]', :text => /Next/
1525 1536 assert_select 'span.position', :text => "2 of 4"
1526 1537 end
1527 1538 end
1528 1539
1529 1540 def test_show_should_display_category_field_if_categories_are_defined
1530 1541 Issue.update_all :category_id => nil
1531 1542
1532 1543 get :show, :id => 1
1533 1544 assert_response :success
1534 1545 assert_select '.attributes .category'
1535 1546 end
1536 1547
1537 1548 def test_show_should_not_display_category_field_if_no_categories_are_defined
1538 1549 Project.find(1).issue_categories.delete_all
1539 1550
1540 1551 get :show, :id => 1
1541 1552 assert_response :success
1542 1553 assert_select 'table.attributes .category', 0
1543 1554 end
1544 1555
1545 1556 def test_show_should_display_link_to_the_assignee
1546 1557 get :show, :id => 2
1547 1558 assert_response :success
1548 1559 assert_select '.assigned-to' do
1549 1560 assert_select 'a[href="/users/3"]'
1550 1561 end
1551 1562 end
1552 1563
1553 1564 def test_show_should_display_visible_changesets_from_other_projects
1554 1565 project = Project.find(2)
1555 1566 issue = project.issues.first
1556 1567 issue.changeset_ids = [102]
1557 1568 issue.save!
1558 1569 # changesets from other projects should be displayed even if repository
1559 1570 # is disabled on issue's project
1560 1571 project.disable_module! :repository
1561 1572
1562 1573 @request.session[:user_id] = 2
1563 1574 get :show, :id => issue.id
1564 1575
1565 1576 assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
1566 1577 end
1567 1578
1568 1579 def test_show_should_display_watchers
1569 1580 @request.session[:user_id] = 2
1570 1581 Issue.find(1).add_watcher User.find(2)
1571 1582
1572 1583 get :show, :id => 1
1573 1584 assert_select 'div#watchers ul' do
1574 1585 assert_select 'li' do
1575 1586 assert_select 'a[href="/users/2"]'
1576 1587 assert_select 'a[class*=delete]'
1577 1588 end
1578 1589 end
1579 1590 end
1580 1591
1581 1592 def test_show_should_display_watchers_with_gravatars
1582 1593 @request.session[:user_id] = 2
1583 1594 Issue.find(1).add_watcher User.find(2)
1584 1595
1585 1596 with_settings :gravatar_enabled => '1' do
1586 1597 get :show, :id => 1
1587 1598 end
1588 1599
1589 1600 assert_select 'div#watchers ul' do
1590 1601 assert_select 'li' do
1591 1602 assert_select 'img.gravatar'
1592 1603 assert_select 'a[href="/users/2"]'
1593 1604 assert_select 'a[class*=delete]'
1594 1605 end
1595 1606 end
1596 1607 end
1597 1608
1598 1609 def test_show_with_thumbnails_enabled_should_display_thumbnails
1599 1610 @request.session[:user_id] = 2
1600 1611
1601 1612 with_settings :thumbnails_enabled => '1' do
1602 1613 get :show, :id => 14
1603 1614 assert_response :success
1604 1615 end
1605 1616
1606 1617 assert_select 'div.thumbnails' do
1607 1618 assert_select 'a[href="/attachments/16/testfile.png"]' do
1608 1619 assert_select 'img[src="/attachments/thumbnail/16"]'
1609 1620 end
1610 1621 end
1611 1622 end
1612 1623
1613 1624 def test_show_with_thumbnails_disabled_should_not_display_thumbnails
1614 1625 @request.session[:user_id] = 2
1615 1626
1616 1627 with_settings :thumbnails_enabled => '0' do
1617 1628 get :show, :id => 14
1618 1629 assert_response :success
1619 1630 end
1620 1631
1621 1632 assert_select 'div.thumbnails', 0
1622 1633 end
1623 1634
1624 1635 def test_show_with_multi_custom_field
1625 1636 field = CustomField.find(1)
1626 1637 field.update_attribute :multiple, true
1627 1638 issue = Issue.find(1)
1628 1639 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1629 1640 issue.save!
1630 1641
1631 1642 get :show, :id => 1
1632 1643 assert_response :success
1633 1644
1634 1645 assert_select ".cf_1 .value", :text => 'MySQL, Oracle'
1635 1646 end
1636 1647
1637 1648 def test_show_with_multi_user_custom_field
1638 1649 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1639 1650 :tracker_ids => [1], :is_for_all => true)
1640 1651 issue = Issue.find(1)
1641 1652 issue.custom_field_values = {field.id => ['2', '3']}
1642 1653 issue.save!
1643 1654
1644 1655 get :show, :id => 1
1645 1656 assert_response :success
1646 1657
1647 1658 assert_select ".cf_#{field.id} .value", :text => 'Dave Lopper, John Smith' do
1648 1659 assert_select 'a', :text => 'Dave Lopper'
1649 1660 assert_select 'a', :text => 'John Smith'
1650 1661 end
1651 1662 end
1652 1663
1653 1664 def test_show_should_display_private_notes_with_permission_only
1654 1665 journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
1655 1666 @request.session[:user_id] = 2
1656 1667
1657 1668 get :show, :id => 2
1658 1669 assert_response :success
1659 1670 assert_include journal, assigns(:journals)
1660 1671
1661 1672 Role.find(1).remove_permission! :view_private_notes
1662 1673 get :show, :id => 2
1663 1674 assert_response :success
1664 1675 assert_not_include journal, assigns(:journals)
1665 1676 end
1666 1677
1667 1678 def test_show_atom
1668 1679 get :show, :id => 2, :format => 'atom'
1669 1680 assert_response :success
1670 1681 assert_template 'journals/index'
1671 1682 # Inline image
1672 1683 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1673 1684 end
1674 1685
1675 1686 def test_show_export_to_pdf
1676 1687 issue = Issue.find(3)
1677 1688 assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1678 1689 get :show, :id => 3, :format => 'pdf'
1679 1690 assert_response :success
1680 1691 assert_equal 'application/pdf', @response.content_type
1681 1692 assert @response.body.starts_with?('%PDF')
1682 1693 assert_not_nil assigns(:issue)
1683 1694 end
1684 1695
1685 1696 def test_export_to_pdf_with_utf8_u_fffd
1686 1697 # U+FFFD
1687 1698 s = "\xef\xbf\xbd"
1688 1699 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
1689 1700 issue = Issue.generate!(:subject => s)
1690 1701 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
1691 1702 with_settings :default_language => lang do
1692 1703 get :show, :id => issue.id, :format => 'pdf'
1693 1704 assert_response :success
1694 1705 assert_equal 'application/pdf', @response.content_type
1695 1706 assert @response.body.starts_with?('%PDF')
1696 1707 assert_not_nil assigns(:issue)
1697 1708 end
1698 1709 end
1699 1710 end
1700 1711
1701 1712 def test_show_export_to_pdf_with_ancestors
1702 1713 issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1703 1714
1704 1715 get :show, :id => issue.id, :format => 'pdf'
1705 1716 assert_response :success
1706 1717 assert_equal 'application/pdf', @response.content_type
1707 1718 assert @response.body.starts_with?('%PDF')
1708 1719 end
1709 1720
1710 1721 def test_show_export_to_pdf_with_descendants
1711 1722 c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1712 1723 c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1713 1724 c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
1714 1725
1715 1726 get :show, :id => 1, :format => 'pdf'
1716 1727 assert_response :success
1717 1728 assert_equal 'application/pdf', @response.content_type
1718 1729 assert @response.body.starts_with?('%PDF')
1719 1730 end
1720 1731
1721 1732 def test_show_export_to_pdf_with_journals
1722 1733 get :show, :id => 1, :format => 'pdf'
1723 1734 assert_response :success
1724 1735 assert_equal 'application/pdf', @response.content_type
1725 1736 assert @response.body.starts_with?('%PDF')
1726 1737 end
1727 1738
1728 1739 def test_show_export_to_pdf_with_changesets
1729 1740 [[100], [100, 101], [100, 101, 102]].each do |cs|
1730 1741 issue1 = Issue.find(3)
1731 1742 issue1.changesets = Changeset.find(cs)
1732 1743 issue1.save!
1733 1744 issue = Issue.find(3)
1734 1745 assert_equal issue.changesets.count, cs.size
1735 1746 get :show, :id => 3, :format => 'pdf'
1736 1747 assert_response :success
1737 1748 assert_equal 'application/pdf', @response.content_type
1738 1749 assert @response.body.starts_with?('%PDF')
1739 1750 end
1740 1751 end
1741 1752
1742 1753 def test_show_invalid_should_respond_with_404
1743 1754 get :show, :id => 999
1744 1755 assert_response 404
1745 1756 end
1746 1757
1747 1758 def test_get_new
1748 1759 @request.session[:user_id] = 2
1749 1760 get :new, :project_id => 1, :tracker_id => 1
1750 1761 assert_response :success
1751 1762 assert_template 'new'
1752 1763
1753 1764 assert_select 'form#issue-form[action=?]', '/projects/ecookbook/issues'
1754 1765 assert_select 'form#issue-form' do
1755 1766 assert_select 'input[name=?]', 'issue[is_private]'
1756 1767 assert_select 'select[name=?]', 'issue[project_id]', 0
1757 1768 assert_select 'select[name=?]', 'issue[tracker_id]'
1758 1769 assert_select 'input[name=?]', 'issue[subject]'
1759 1770 assert_select 'textarea[name=?]', 'issue[description]'
1760 1771 assert_select 'select[name=?]', 'issue[status_id]'
1761 1772 assert_select 'select[name=?]', 'issue[priority_id]'
1762 1773 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1763 1774 assert_select 'select[name=?]', 'issue[category_id]'
1764 1775 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1765 1776 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1766 1777 assert_select 'input[name=?]', 'issue[start_date]'
1767 1778 assert_select 'input[name=?]', 'issue[due_date]'
1768 1779 assert_select 'select[name=?]', 'issue[done_ratio]'
1769 1780 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1770 1781 assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
1771 1782 end
1772 1783
1773 1784 # Be sure we don't display inactive IssuePriorities
1774 1785 assert ! IssuePriority.find(15).active?
1775 1786 assert_select 'select[name=?]', 'issue[priority_id]' do
1776 1787 assert_select 'option[value="15"]', 0
1777 1788 end
1778 1789 end
1779 1790
1780 1791 def test_get_new_with_minimal_permissions
1781 1792 Role.find(1).update_attribute :permissions, [:add_issues]
1782 1793 WorkflowTransition.delete_all :role_id => 1
1783 1794
1784 1795 @request.session[:user_id] = 2
1785 1796 get :new, :project_id => 1, :tracker_id => 1
1786 1797 assert_response :success
1787 1798 assert_template 'new'
1788 1799
1789 1800 assert_select 'form#issue-form' do
1790 1801 assert_select 'input[name=?]', 'issue[is_private]', 0
1791 1802 assert_select 'select[name=?]', 'issue[project_id]', 0
1792 1803 assert_select 'select[name=?]', 'issue[tracker_id]'
1793 1804 assert_select 'input[name=?]', 'issue[subject]'
1794 1805 assert_select 'textarea[name=?]', 'issue[description]'
1795 1806 assert_select 'select[name=?]', 'issue[status_id]'
1796 1807 assert_select 'select[name=?]', 'issue[priority_id]'
1797 1808 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1798 1809 assert_select 'select[name=?]', 'issue[category_id]'
1799 1810 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1800 1811 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1801 1812 assert_select 'input[name=?]', 'issue[start_date]'
1802 1813 assert_select 'input[name=?]', 'issue[due_date]'
1803 1814 assert_select 'select[name=?]', 'issue[done_ratio]'
1804 1815 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1805 1816 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1806 1817 end
1807 1818 end
1808 1819
1809 1820 def test_new_without_project_id
1810 1821 @request.session[:user_id] = 2
1811 1822 get :new
1812 1823 assert_response :success
1813 1824 assert_template 'new'
1814 1825
1815 1826 assert_select 'form#issue-form[action=?]', '/issues'
1816 1827 assert_select 'form#issue-form' do
1817 1828 assert_select 'select[name=?]', 'issue[project_id]'
1818 1829 end
1819 1830
1820 1831 assert_nil assigns(:project)
1821 1832 assert_not_nil assigns(:issue)
1822 1833 end
1823 1834
1824 1835 def test_new_should_select_default_status
1825 1836 @request.session[:user_id] = 2
1826 1837
1827 1838 get :new, :project_id => 1
1828 1839 assert_response :success
1829 1840 assert_template 'new'
1830 1841 assert_select 'select[name=?]', 'issue[status_id]' do
1831 1842 assert_select 'option[value="1"][selected=selected]'
1832 1843 end
1833 1844 assert_select 'input[name=was_default_status][value="1"]'
1834 1845 end
1835 1846
1836 1847 def test_new_should_propose_allowed_statuses
1837 1848 WorkflowTransition.delete_all
1838 1849 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 1)
1839 1850 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 3)
1840 1851 @request.session[:user_id] = 2
1841 1852
1842 1853 get :new, :project_id => 1
1843 1854 assert_response :success
1844 1855 assert_select 'select[name=?]', 'issue[status_id]' do
1845 1856 assert_select 'option[value="1"]'
1846 1857 assert_select 'option[value="3"]'
1847 1858 assert_select 'option', 2
1848 1859 assert_select 'option[value="1"][selected=selected]'
1849 1860 end
1850 1861 end
1851 1862
1852 1863 def test_new_should_propose_allowed_statuses_without_default_status_allowed
1853 1864 WorkflowTransition.delete_all
1854 1865 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 2)
1855 1866 assert_equal 1, Tracker.find(1).default_status_id
1856 1867 @request.session[:user_id] = 2
1857 1868
1858 1869 get :new, :project_id => 1
1859 1870 assert_response :success
1860 1871 assert_select 'select[name=?]', 'issue[status_id]' do
1861 1872 assert_select 'option[value="2"]'
1862 1873 assert_select 'option', 1
1863 1874 assert_select 'option[value="2"][selected=selected]'
1864 1875 end
1865 1876 end
1866 1877
1867 1878 def test_new_should_propose_allowed_trackers
1868 1879 role = Role.find(1)
1869 1880 role.set_permission_trackers 'add_issues', [1, 3]
1870 1881 role.save!
1871 1882 @request.session[:user_id] = 2
1872 1883
1873 1884 get :new, :project_id => 1
1874 1885 assert_response :success
1875 1886 assert_select 'select[name=?]', 'issue[tracker_id]' do
1876 1887 assert_select 'option', 2
1877 1888 assert_select 'option[value="1"]'
1878 1889 assert_select 'option[value="3"]'
1879 1890 end
1880 1891 end
1881 1892
1882 1893 def test_new_without_allowed_trackers_should_respond_with_403
1883 1894 role = Role.find(1)
1884 1895 role.set_permission_trackers 'add_issues', []
1885 1896 role.save!
1886 1897 @request.session[:user_id] = 2
1887 1898
1888 1899 get :new, :project_id => 1
1889 1900 assert_response 403
1890 1901 end
1891 1902
1892 1903 def test_new_should_preselect_default_version
1893 1904 version = Version.generate!(:project_id => 1)
1894 1905 Project.find(1).update_attribute :default_version_id, version.id
1895 1906 @request.session[:user_id] = 2
1896 1907
1897 1908 get :new, :project_id => 1
1898 1909 assert_response :success
1899 1910 assert_equal version, assigns(:issue).fixed_version
1900 1911 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
1901 1912 assert_select 'option[value=?][selected=selected]', version.id.to_s
1902 1913 end
1903 1914 end
1904 1915
1905 1916 def test_get_new_with_list_custom_field
1906 1917 @request.session[:user_id] = 2
1907 1918 get :new, :project_id => 1, :tracker_id => 1
1908 1919 assert_response :success
1909 1920 assert_template 'new'
1910 1921
1911 1922 assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
1912 1923 assert_select 'option', 4
1913 1924 assert_select 'option[value=MySQL]', :text => 'MySQL'
1914 1925 end
1915 1926 end
1916 1927
1917 1928 def test_get_new_with_multi_custom_field
1918 1929 field = IssueCustomField.find(1)
1919 1930 field.update_attribute :multiple, true
1920 1931
1921 1932 @request.session[:user_id] = 2
1922 1933 get :new, :project_id => 1, :tracker_id => 1
1923 1934 assert_response :success
1924 1935 assert_template 'new'
1925 1936
1926 1937 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
1927 1938 assert_select 'option', 3
1928 1939 assert_select 'option[value=MySQL]', :text => 'MySQL'
1929 1940 end
1930 1941 assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
1931 1942 end
1932 1943
1933 1944 def test_get_new_with_multi_user_custom_field
1934 1945 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1935 1946 :tracker_ids => [1], :is_for_all => true)
1936 1947
1937 1948 @request.session[:user_id] = 2
1938 1949 get :new, :project_id => 1, :tracker_id => 1
1939 1950 assert_response :success
1940 1951 assert_template 'new'
1941 1952
1942 1953 assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
1943 1954 assert_select 'option', Project.find(1).users.count
1944 1955 assert_select 'option[value="2"]', :text => 'John Smith'
1945 1956 end
1946 1957 assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
1947 1958 end
1948 1959
1949 1960 def test_get_new_with_date_custom_field
1950 1961 field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
1951 1962
1952 1963 @request.session[:user_id] = 2
1953 1964 get :new, :project_id => 1, :tracker_id => 1
1954 1965 assert_response :success
1955 1966
1956 1967 assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
1957 1968 end
1958 1969
1959 1970 def test_get_new_with_text_custom_field
1960 1971 field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
1961 1972
1962 1973 @request.session[:user_id] = 2
1963 1974 get :new, :project_id => 1, :tracker_id => 1
1964 1975 assert_response :success
1965 1976
1966 1977 assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
1967 1978 end
1968 1979
1969 1980 def test_get_new_without_default_start_date_is_creation_date
1970 1981 with_settings :default_issue_start_date_to_creation_date => 0 do
1971 1982 @request.session[:user_id] = 2
1972 1983 get :new, :project_id => 1, :tracker_id => 1
1973 1984 assert_response :success
1974 1985 assert_template 'new'
1975 1986 assert_select 'input[name=?]', 'issue[start_date]'
1976 1987 assert_select 'input[name=?][value]', 'issue[start_date]', 0
1977 1988 end
1978 1989 end
1979 1990
1980 1991 def test_get_new_with_default_start_date_is_creation_date
1981 1992 with_settings :default_issue_start_date_to_creation_date => 1 do
1982 1993 @request.session[:user_id] = 2
1983 1994 get :new, :project_id => 1, :tracker_id => 1
1984 1995 assert_response :success
1985 1996 assert_template 'new'
1986 1997 assert_select 'input[name=?][value=?]', 'issue[start_date]',
1987 1998 Date.today.to_s
1988 1999 end
1989 2000 end
1990 2001
1991 2002 def test_get_new_form_should_allow_attachment_upload
1992 2003 @request.session[:user_id] = 2
1993 2004 get :new, :project_id => 1, :tracker_id => 1
1994 2005
1995 2006 assert_select 'form[id=issue-form][method=post][enctype="multipart/form-data"]' do
1996 2007 assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
1997 2008 end
1998 2009 end
1999 2010
2000 2011 def test_get_new_should_prefill_the_form_from_params
2001 2012 @request.session[:user_id] = 2
2002 2013 get :new, :project_id => 1,
2003 2014 :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
2004 2015
2005 2016 issue = assigns(:issue)
2006 2017 assert_equal 3, issue.tracker_id
2007 2018 assert_equal 'Prefilled', issue.description
2008 2019 assert_equal 'Custom field value', issue.custom_field_value(2)
2009 2020
2010 2021 assert_select 'select[name=?]', 'issue[tracker_id]' do
2011 2022 assert_select 'option[value="3"][selected=selected]'
2012 2023 end
2013 2024 assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
2014 2025 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
2015 2026 end
2016 2027
2017 2028 def test_get_new_should_mark_required_fields
2018 2029 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2019 2030 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2020 2031 WorkflowPermission.delete_all
2021 2032 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
2022 2033 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2023 2034 @request.session[:user_id] = 2
2024 2035
2025 2036 get :new, :project_id => 1
2026 2037 assert_response :success
2027 2038 assert_template 'new'
2028 2039
2029 2040 assert_select 'label[for=issue_start_date]' do
2030 2041 assert_select 'span[class=required]', 0
2031 2042 end
2032 2043 assert_select 'label[for=issue_due_date]' do
2033 2044 assert_select 'span[class=required]'
2034 2045 end
2035 2046 assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
2036 2047 assert_select 'span[class=required]', 0
2037 2048 end
2038 2049 assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
2039 2050 assert_select 'span[class=required]'
2040 2051 end
2041 2052 end
2042 2053
2043 2054 def test_get_new_should_not_display_readonly_fields
2044 2055 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2045 2056 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2046 2057 WorkflowPermission.delete_all
2047 2058 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
2048 2059 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
2049 2060 @request.session[:user_id] = 2
2050 2061
2051 2062 get :new, :project_id => 1
2052 2063 assert_response :success
2053 2064 assert_template 'new'
2054 2065
2055 2066 assert_select 'input[name=?]', 'issue[start_date]'
2056 2067 assert_select 'input[name=?]', 'issue[due_date]', 0
2057 2068 assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
2058 2069 assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
2059 2070 end
2060 2071
2061 2072 def test_new_with_tracker_set_as_readonly_should_accept_status
2062 2073 WorkflowPermission.delete_all
2063 2074 [1, 2].each do |status_id|
2064 2075 WorkflowPermission.create!(:tracker_id => 1, :old_status_id => status_id, :role_id => 1, :field_name => 'tracker_id', :rule => 'readonly')
2065 2076 end
2066 2077 @request.session[:user_id] = 2
2067 2078
2068 2079 get :new, :project_id => 1, :issue => {:status_id => 2}
2069 2080 assert_select 'select[name=?]', 'issue[tracker_id]', 0
2070 2081 assert_equal 2, assigns(:issue).status_id
2071 2082 end
2072 2083
2073 2084 def test_get_new_without_tracker_id
2074 2085 @request.session[:user_id] = 2
2075 2086 get :new, :project_id => 1
2076 2087 assert_response :success
2077 2088 assert_template 'new'
2078 2089
2079 2090 issue = assigns(:issue)
2080 2091 assert_not_nil issue
2081 2092 assert_equal Project.find(1).trackers.first, issue.tracker
2082 2093 end
2083 2094
2084 2095 def test_get_new_with_no_default_status_should_display_an_error
2085 2096 @request.session[:user_id] = 2
2086 2097 IssueStatus.delete_all
2087 2098
2088 2099 get :new, :project_id => 1
2089 2100 assert_response 500
2090 2101 assert_select_error /No default issue/
2091 2102 end
2092 2103
2093 2104 def test_get_new_with_no_tracker_should_display_an_error
2094 2105 @request.session[:user_id] = 2
2095 2106 Tracker.delete_all
2096 2107
2097 2108 get :new, :project_id => 1
2098 2109 assert_response 500
2099 2110 assert_select_error /No tracker/
2100 2111 end
2101 2112
2102 2113 def test_new_with_invalid_project_id
2103 2114 @request.session[:user_id] = 1
2104 2115 get :new, :project_id => 'invalid'
2105 2116 assert_response 404
2106 2117 end
2107 2118
2108 2119 def test_new_with_parent_id_should_only_propose_valid_trackers
2109 2120 @request.session[:user_id] = 2
2110 2121 t = Tracker.find(3)
2111 2122 assert !t.disabled_core_fields.include?('parent_issue_id')
2112 2123
2113 2124 get :new, :project_id => 1, issue: { parent_issue_id: 1 }
2114 2125 assert_response :success
2115 2126 assert_select 'option', text: /#{t.name}/, count: 1
2116 2127
2117 2128 t.core_fields = Tracker::CORE_FIELDS - ['parent_issue_id']
2118 2129 t.save!
2119 2130 assert t.disabled_core_fields.include?('parent_issue_id')
2120 2131 get :new, :project_id => 1, issue: { parent_issue_id: 1 }
2121 2132 assert_response :success
2122 2133 assert_select 'option', text: /#{t.name}/, count: 0
2123 2134 end
2124 2135
2125 2136 def test_update_form_for_new_issue
2126 2137 @request.session[:user_id] = 2
2127 2138 xhr :post, :new, :project_id => 1,
2128 2139 :issue => {:tracker_id => 2,
2129 2140 :subject => 'This is the test_new issue',
2130 2141 :description => 'This is the description',
2131 2142 :priority_id => 5}
2132 2143 assert_response :success
2133 2144 assert_template 'new'
2134 2145 assert_template :partial => '_form'
2135 2146 assert_equal 'text/javascript', response.content_type
2136 2147
2137 2148 issue = assigns(:issue)
2138 2149 assert_kind_of Issue, issue
2139 2150 assert_equal 1, issue.project_id
2140 2151 assert_equal 2, issue.tracker_id
2141 2152 assert_equal 'This is the test_new issue', issue.subject
2142 2153 end
2143 2154
2144 2155 def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
2145 2156 @request.session[:user_id] = 2
2146 2157 WorkflowTransition.delete_all
2147 2158 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 2)
2148 2159 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 5)
2149 2160 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
2150 2161
2151 2162 xhr :post, :new, :project_id => 1,
2152 2163 :issue => {:tracker_id => 1,
2153 2164 :status_id => 5,
2154 2165 :subject => 'This is an issue'}
2155 2166
2156 2167 assert_equal 5, assigns(:issue).status_id
2157 2168 assert_equal [2,5], assigns(:allowed_statuses).map(&:id).sort
2158 2169 end
2159 2170
2160 2171 def test_update_form_with_default_status_should_ignore_submitted_status_id_if_equals
2161 2172 @request.session[:user_id] = 2
2162 2173 tracker = Tracker.find(2)
2163 2174 tracker.update! :default_status_id => 2
2164 2175 tracker.generate_transitions! 2, 1, :clear => true
2165 2176
2166 2177 xhr :post, :new, :project_id => 1,
2167 2178 :issue => {:tracker_id => 2,
2168 2179 :status_id => 1},
2169 2180 :was_default_status => 1
2170 2181
2171 2182 assert_equal 2, assigns(:issue).status_id
2172 2183 end
2173 2184
2174 2185 def test_update_form_for_new_issue_should_ignore_version_when_changing_project
2175 2186 version = Version.generate!(:project_id => 1)
2176 2187 Project.find(1).update_attribute :default_version_id, version.id
2177 2188 @request.session[:user_id] = 2
2178 2189
2179 2190 xhr :post, :new, :issue => {:project_id => 1,
2180 2191 :fixed_version_id => ''},
2181 2192 :form_update_triggered_by => 'issue_project_id'
2182 2193 assert_response :success
2183 2194 assert_template 'new'
2184 2195
2185 2196 issue = assigns(:issue)
2186 2197 assert_equal 1, issue.project_id
2187 2198 assert_equal version, issue.fixed_version
2188 2199 end
2189 2200
2190 2201 def test_post_create
2191 2202 @request.session[:user_id] = 2
2192 2203 assert_difference 'Issue.count' do
2193 2204 assert_no_difference 'Journal.count' do
2194 2205 post :create, :project_id => 1,
2195 2206 :issue => {:tracker_id => 3,
2196 2207 :status_id => 2,
2197 2208 :subject => 'This is the test_new issue',
2198 2209 :description => 'This is the description',
2199 2210 :priority_id => 5,
2200 2211 :start_date => '2010-11-07',
2201 2212 :estimated_hours => '',
2202 2213 :custom_field_values => {'2' => 'Value for field 2'}}
2203 2214 end
2204 2215 end
2205 2216 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2206 2217
2207 2218 issue = Issue.find_by_subject('This is the test_new issue')
2208 2219 assert_not_nil issue
2209 2220 assert_equal 2, issue.author_id
2210 2221 assert_equal 3, issue.tracker_id
2211 2222 assert_equal 2, issue.status_id
2212 2223 assert_equal Date.parse('2010-11-07'), issue.start_date
2213 2224 assert_nil issue.estimated_hours
2214 2225 v = issue.custom_values.where(:custom_field_id => 2).first
2215 2226 assert_not_nil v
2216 2227 assert_equal 'Value for field 2', v.value
2217 2228 end
2218 2229
2219 2230 def test_post_new_with_group_assignment
2220 2231 group = Group.find(11)
2221 2232 project = Project.find(1)
2222 2233 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
2223 2234
2224 2235 with_settings :issue_group_assignment => '1' do
2225 2236 @request.session[:user_id] = 2
2226 2237 assert_difference 'Issue.count' do
2227 2238 post :create, :project_id => project.id,
2228 2239 :issue => {:tracker_id => 3,
2229 2240 :status_id => 1,
2230 2241 :subject => 'This is the test_new_with_group_assignment issue',
2231 2242 :assigned_to_id => group.id}
2232 2243 end
2233 2244 end
2234 2245 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2235 2246
2236 2247 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
2237 2248 assert_not_nil issue
2238 2249 assert_equal group, issue.assigned_to
2239 2250 end
2240 2251
2241 2252 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
2242 2253 with_settings :default_issue_start_date_to_creation_date => 0 do
2243 2254 @request.session[:user_id] = 2
2244 2255 assert_difference 'Issue.count' do
2245 2256 post :create, :project_id => 1,
2246 2257 :issue => {:tracker_id => 3,
2247 2258 :status_id => 2,
2248 2259 :subject => 'This is the test_new issue',
2249 2260 :description => 'This is the description',
2250 2261 :priority_id => 5,
2251 2262 :estimated_hours => '',
2252 2263 :custom_field_values => {'2' => 'Value for field 2'}}
2253 2264 end
2254 2265 assert_redirected_to :controller => 'issues', :action => 'show',
2255 2266 :id => Issue.last.id
2256 2267 issue = Issue.find_by_subject('This is the test_new issue')
2257 2268 assert_not_nil issue
2258 2269 assert_nil issue.start_date
2259 2270 end
2260 2271 end
2261 2272
2262 2273 def test_post_create_without_start_date_and_default_start_date_is_creation_date
2263 2274 with_settings :default_issue_start_date_to_creation_date => 1 do
2264 2275 @request.session[:user_id] = 2
2265 2276 assert_difference 'Issue.count' do
2266 2277 post :create, :project_id => 1,
2267 2278 :issue => {:tracker_id => 3,
2268 2279 :status_id => 2,
2269 2280 :subject => 'This is the test_new issue',
2270 2281 :description => 'This is the description',
2271 2282 :priority_id => 5,
2272 2283 :estimated_hours => '',
2273 2284 :custom_field_values => {'2' => 'Value for field 2'}}
2274 2285 end
2275 2286 assert_redirected_to :controller => 'issues', :action => 'show',
2276 2287 :id => Issue.last.id
2277 2288 issue = Issue.find_by_subject('This is the test_new issue')
2278 2289 assert_not_nil issue
2279 2290 assert_equal Date.today, issue.start_date
2280 2291 end
2281 2292 end
2282 2293
2283 2294 def test_post_create_and_continue
2284 2295 @request.session[:user_id] = 2
2285 2296 assert_difference 'Issue.count' do
2286 2297 post :create, :project_id => 1,
2287 2298 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
2288 2299 :continue => ''
2289 2300 end
2290 2301
2291 2302 issue = Issue.order('id DESC').first
2292 2303 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
2293 2304 assert_not_nil flash[:notice], "flash was not set"
2294 2305 assert_select_in flash[:notice],
2295 2306 'a[href=?][title=?]', "/issues/#{issue.id}", "This is first issue", :text => "##{issue.id}"
2296 2307 end
2297 2308
2298 2309 def test_post_create_without_custom_fields_param
2299 2310 @request.session[:user_id] = 2
2300 2311 assert_difference 'Issue.count' do
2301 2312 post :create, :project_id => 1,
2302 2313 :issue => {:tracker_id => 1,
2303 2314 :subject => 'This is the test_new issue',
2304 2315 :description => 'This is the description',
2305 2316 :priority_id => 5}
2306 2317 end
2307 2318 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2308 2319 end
2309 2320
2310 2321 def test_post_create_with_multi_custom_field
2311 2322 field = IssueCustomField.find_by_name('Database')
2312 2323 field.update_attribute(:multiple, true)
2313 2324
2314 2325 @request.session[:user_id] = 2
2315 2326 assert_difference 'Issue.count' do
2316 2327 post :create, :project_id => 1,
2317 2328 :issue => {:tracker_id => 1,
2318 2329 :subject => 'This is the test_new issue',
2319 2330 :description => 'This is the description',
2320 2331 :priority_id => 5,
2321 2332 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
2322 2333 end
2323 2334 assert_response 302
2324 2335 issue = Issue.order('id DESC').first
2325 2336 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
2326 2337 end
2327 2338
2328 2339 def test_post_create_with_empty_multi_custom_field
2329 2340 field = IssueCustomField.find_by_name('Database')
2330 2341 field.update_attribute(:multiple, true)
2331 2342
2332 2343 @request.session[:user_id] = 2
2333 2344 assert_difference 'Issue.count' do
2334 2345 post :create, :project_id => 1,
2335 2346 :issue => {:tracker_id => 1,
2336 2347 :subject => 'This is the test_new issue',
2337 2348 :description => 'This is the description',
2338 2349 :priority_id => 5,
2339 2350 :custom_field_values => {'1' => ['']}}
2340 2351 end
2341 2352 assert_response 302
2342 2353 issue = Issue.order('id DESC').first
2343 2354 assert_equal [''], issue.custom_field_value(1).sort
2344 2355 end
2345 2356
2346 2357 def test_post_create_with_multi_user_custom_field
2347 2358 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
2348 2359 :tracker_ids => [1], :is_for_all => true)
2349 2360
2350 2361 @request.session[:user_id] = 2
2351 2362 assert_difference 'Issue.count' do
2352 2363 post :create, :project_id => 1,
2353 2364 :issue => {:tracker_id => 1,
2354 2365 :subject => 'This is the test_new issue',
2355 2366 :description => 'This is the description',
2356 2367 :priority_id => 5,
2357 2368 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
2358 2369 end
2359 2370 assert_response 302
2360 2371 issue = Issue.order('id DESC').first
2361 2372 assert_equal ['2', '3'], issue.custom_field_value(field).sort
2362 2373 end
2363 2374
2364 2375 def test_post_create_with_required_custom_field_and_without_custom_fields_param
2365 2376 field = IssueCustomField.find_by_name('Database')
2366 2377 field.update_attribute(:is_required, true)
2367 2378
2368 2379 @request.session[:user_id] = 2
2369 2380 assert_no_difference 'Issue.count' do
2370 2381 post :create, :project_id => 1,
2371 2382 :issue => {:tracker_id => 1,
2372 2383 :subject => 'This is the test_new issue',
2373 2384 :description => 'This is the description',
2374 2385 :priority_id => 5}
2375 2386 end
2376 2387 assert_response :success
2377 2388 assert_template 'new'
2378 2389 issue = assigns(:issue)
2379 2390 assert_not_nil issue
2380 2391 assert_select_error /Database cannot be blank/
2381 2392 end
2382 2393
2383 2394 def test_create_should_validate_required_fields
2384 2395 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2385 2396 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2386 2397 WorkflowPermission.delete_all
2387 2398 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
2388 2399 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2389 2400 @request.session[:user_id] = 2
2390 2401
2391 2402 assert_no_difference 'Issue.count' do
2392 2403 post :create, :project_id => 1, :issue => {
2393 2404 :tracker_id => 2,
2394 2405 :status_id => 1,
2395 2406 :subject => 'Test',
2396 2407 :start_date => '',
2397 2408 :due_date => '',
2398 2409 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
2399 2410 }
2400 2411 assert_response :success
2401 2412 assert_template 'new'
2402 2413 end
2403 2414
2404 2415 assert_select_error /Due date cannot be blank/i
2405 2416 assert_select_error /Bar cannot be blank/i
2406 2417 end
2407 2418
2408 2419 def test_create_should_validate_required_list_fields
2409 2420 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => false, :possible_values => ['a', 'b'])
2410 2421 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => true, :possible_values => ['a', 'b'])
2411 2422 WorkflowPermission.delete_all
2412 2423 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf1.id.to_s, :rule => 'required')
2413 2424 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2414 2425 @request.session[:user_id] = 2
2415 2426
2416 2427 assert_no_difference 'Issue.count' do
2417 2428 post :create, :project_id => 1, :issue => {
2418 2429 :tracker_id => 2,
2419 2430 :status_id => 1,
2420 2431 :subject => 'Test',
2421 2432 :start_date => '',
2422 2433 :due_date => '',
2423 2434 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ['']}
2424 2435 }
2425 2436 assert_response :success
2426 2437 assert_template 'new'
2427 2438 end
2428 2439
2429 2440 assert_select_error /Foo cannot be blank/i
2430 2441 assert_select_error /Bar cannot be blank/i
2431 2442 end
2432 2443
2433 2444 def test_create_should_ignore_readonly_fields
2434 2445 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2435 2446 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2436 2447 WorkflowPermission.delete_all
2437 2448 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
2438 2449 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
2439 2450 @request.session[:user_id] = 2
2440 2451
2441 2452 assert_difference 'Issue.count' do
2442 2453 post :create, :project_id => 1, :issue => {
2443 2454 :tracker_id => 2,
2444 2455 :status_id => 1,
2445 2456 :subject => 'Test',
2446 2457 :start_date => '2012-07-14',
2447 2458 :due_date => '2012-07-16',
2448 2459 :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
2449 2460 }
2450 2461 assert_response 302
2451 2462 end
2452 2463
2453 2464 issue = Issue.order('id DESC').first
2454 2465 assert_equal Date.parse('2012-07-14'), issue.start_date
2455 2466 assert_nil issue.due_date
2456 2467 assert_equal 'value1', issue.custom_field_value(cf1)
2457 2468 assert_nil issue.custom_field_value(cf2)
2458 2469 end
2459 2470
2460 2471 def test_create_should_ignore_unallowed_trackers
2461 2472 role = Role.find(1)
2462 2473 role.set_permission_trackers :add_issues, [3]
2463 2474 role.save!
2464 2475 @request.session[:user_id] = 2
2465 2476
2466 2477 issue = new_record(Issue) do
2467 2478 post :create, :project_id => 1, :issue => {
2468 2479 :tracker_id => 1,
2469 2480 :status_id => 1,
2470 2481 :subject => 'Test'
2471 2482 }
2472 2483 assert_response 302
2473 2484 end
2474 2485 assert_equal 3, issue.tracker_id
2475 2486 end
2476 2487
2477 2488 def test_post_create_with_watchers
2478 2489 @request.session[:user_id] = 2
2479 2490 ActionMailer::Base.deliveries.clear
2480 2491
2481 2492 with_settings :notified_events => %w(issue_added) do
2482 2493 assert_difference 'Watcher.count', 2 do
2483 2494 post :create, :project_id => 1,
2484 2495 :issue => {:tracker_id => 1,
2485 2496 :subject => 'This is a new issue with watchers',
2486 2497 :description => 'This is the description',
2487 2498 :priority_id => 5,
2488 2499 :watcher_user_ids => ['2', '3']}
2489 2500 end
2490 2501 end
2491 2502 issue = Issue.find_by_subject('This is a new issue with watchers')
2492 2503 assert_not_nil issue
2493 2504 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
2494 2505
2495 2506 # Watchers added
2496 2507 assert_equal [2, 3], issue.watcher_user_ids.sort
2497 2508 assert issue.watched_by?(User.find(3))
2498 2509 # Watchers notified
2499 2510 mail = ActionMailer::Base.deliveries.last
2500 2511 assert_not_nil mail
2501 2512 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
2502 2513 end
2503 2514
2504 2515 def test_post_create_subissue
2505 2516 @request.session[:user_id] = 2
2506 2517
2507 2518 assert_difference 'Issue.count' do
2508 2519 post :create, :project_id => 1,
2509 2520 :issue => {:tracker_id => 1,
2510 2521 :subject => 'This is a child issue',
2511 2522 :parent_issue_id => '2'}
2512 2523 assert_response 302
2513 2524 end
2514 2525 issue = Issue.order('id DESC').first
2515 2526 assert_equal Issue.find(2), issue.parent
2516 2527 end
2517 2528
2518 2529 def test_post_create_subissue_with_sharp_parent_id
2519 2530 @request.session[:user_id] = 2
2520 2531
2521 2532 assert_difference 'Issue.count' do
2522 2533 post :create, :project_id => 1,
2523 2534 :issue => {:tracker_id => 1,
2524 2535 :subject => 'This is a child issue',
2525 2536 :parent_issue_id => '#2'}
2526 2537 assert_response 302
2527 2538 end
2528 2539 issue = Issue.order('id DESC').first
2529 2540 assert_equal Issue.find(2), issue.parent
2530 2541 end
2531 2542
2532 2543 def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
2533 2544 @request.session[:user_id] = 2
2534 2545
2535 2546 assert_no_difference 'Issue.count' do
2536 2547 post :create, :project_id => 1,
2537 2548 :issue => {:tracker_id => 1,
2538 2549 :subject => 'This is a child issue',
2539 2550 :parent_issue_id => '4'}
2540 2551
2541 2552 assert_response :success
2542 2553 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
2543 2554 assert_select_error /Parent task is invalid/i
2544 2555 end
2545 2556 end
2546 2557
2547 2558 def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
2548 2559 @request.session[:user_id] = 2
2549 2560
2550 2561 assert_no_difference 'Issue.count' do
2551 2562 post :create, :project_id => 1,
2552 2563 :issue => {:tracker_id => 1,
2553 2564 :subject => 'This is a child issue',
2554 2565 :parent_issue_id => '01ABC'}
2555 2566
2556 2567 assert_response :success
2557 2568 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
2558 2569 assert_select_error /Parent task is invalid/i
2559 2570 end
2560 2571 end
2561 2572
2562 2573 def test_post_create_private
2563 2574 @request.session[:user_id] = 2
2564 2575
2565 2576 assert_difference 'Issue.count' do
2566 2577 post :create, :project_id => 1,
2567 2578 :issue => {:tracker_id => 1,
2568 2579 :subject => 'This is a private issue',
2569 2580 :is_private => '1'}
2570 2581 end
2571 2582 issue = Issue.order('id DESC').first
2572 2583 assert issue.is_private?
2573 2584 end
2574 2585
2575 2586 def test_post_create_private_with_set_own_issues_private_permission
2576 2587 role = Role.find(1)
2577 2588 role.remove_permission! :set_issues_private
2578 2589 role.add_permission! :set_own_issues_private
2579 2590
2580 2591 @request.session[:user_id] = 2
2581 2592
2582 2593 assert_difference 'Issue.count' do
2583 2594 post :create, :project_id => 1,
2584 2595 :issue => {:tracker_id => 1,
2585 2596 :subject => 'This is a private issue',
2586 2597 :is_private => '1'}
2587 2598 end
2588 2599 issue = Issue.order('id DESC').first
2589 2600 assert issue.is_private?
2590 2601 end
2591 2602
2592 2603 def test_create_without_project_id
2593 2604 @request.session[:user_id] = 2
2594 2605
2595 2606 assert_difference 'Issue.count' do
2596 2607 post :create,
2597 2608 :issue => {:project_id => 3,
2598 2609 :tracker_id => 2,
2599 2610 :subject => 'Foo'}
2600 2611 assert_response 302
2601 2612 end
2602 2613 issue = Issue.order('id DESC').first
2603 2614 assert_equal 3, issue.project_id
2604 2615 assert_equal 2, issue.tracker_id
2605 2616 end
2606 2617
2607 2618 def test_create_without_project_id_and_continue_should_redirect_without_project_id
2608 2619 @request.session[:user_id] = 2
2609 2620
2610 2621 assert_difference 'Issue.count' do
2611 2622 post :create,
2612 2623 :issue => {:project_id => 3,
2613 2624 :tracker_id => 2,
2614 2625 :subject => 'Foo'},
2615 2626 :continue => '1'
2616 2627 assert_redirected_to '/issues/new?issue%5Bproject_id%5D=3&issue%5Btracker_id%5D=2'
2617 2628 end
2618 2629 end
2619 2630
2620 2631 def test_create_without_project_id_should_be_denied_without_permission
2621 2632 Role.non_member.remove_permission! :add_issues
2622 2633 Role.anonymous.remove_permission! :add_issues
2623 2634 @request.session[:user_id] = 2
2624 2635
2625 2636 assert_no_difference 'Issue.count' do
2626 2637 post :create,
2627 2638 :issue => {:project_id => 3,
2628 2639 :tracker_id => 2,
2629 2640 :subject => 'Foo'}
2630 2641 assert_response 422
2631 2642 end
2632 2643 end
2633 2644
2634 2645 def test_create_without_project_id_with_failure
2635 2646 @request.session[:user_id] = 2
2636 2647
2637 2648 post :create,
2638 2649 :issue => {:project_id => 3,
2639 2650 :tracker_id => 2,
2640 2651 :subject => ''}
2641 2652 assert_response :success
2642 2653 assert_nil assigns(:project)
2643 2654 end
2644 2655
2645 2656 def test_post_create_should_send_a_notification
2646 2657 ActionMailer::Base.deliveries.clear
2647 2658 @request.session[:user_id] = 2
2648 2659 with_settings :notified_events => %w(issue_added) do
2649 2660 assert_difference 'Issue.count' do
2650 2661 post :create, :project_id => 1,
2651 2662 :issue => {:tracker_id => 3,
2652 2663 :subject => 'This is the test_new issue',
2653 2664 :description => 'This is the description',
2654 2665 :priority_id => 5,
2655 2666 :estimated_hours => '',
2656 2667 :custom_field_values => {'2' => 'Value for field 2'}}
2657 2668 end
2658 2669 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2659 2670
2660 2671 assert_equal 1, ActionMailer::Base.deliveries.size
2661 2672 end
2662 2673 end
2663 2674
2664 2675 def test_post_create_should_preserve_fields_values_on_validation_failure
2665 2676 @request.session[:user_id] = 2
2666 2677 post :create, :project_id => 1,
2667 2678 :issue => {:tracker_id => 1,
2668 2679 # empty subject
2669 2680 :subject => '',
2670 2681 :description => 'This is a description',
2671 2682 :priority_id => 6,
2672 2683 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
2673 2684 assert_response :success
2674 2685 assert_template 'new'
2675 2686
2676 2687 assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
2677 2688 assert_select 'select[name=?]', 'issue[priority_id]' do
2678 2689 assert_select 'option[value="6"][selected=selected]', :text => 'High'
2679 2690 end
2680 2691 # Custom fields
2681 2692 assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
2682 2693 assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
2683 2694 end
2684 2695 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
2685 2696 end
2686 2697
2687 2698 def test_post_create_with_failure_should_preserve_watchers
2688 2699 assert !User.find(8).member_of?(Project.find(1))
2689 2700
2690 2701 @request.session[:user_id] = 2
2691 2702 post :create, :project_id => 1,
2692 2703 :issue => {:tracker_id => 1,
2693 2704 :watcher_user_ids => ['3', '8']}
2694 2705 assert_response :success
2695 2706 assert_template 'new'
2696 2707
2697 2708 assert_select 'input[name=?][value="2"]:not(checked)', 'issue[watcher_user_ids][]'
2698 2709 assert_select 'input[name=?][value="3"][checked=checked]', 'issue[watcher_user_ids][]'
2699 2710 assert_select 'input[name=?][value="8"][checked=checked]', 'issue[watcher_user_ids][]'
2700 2711 end
2701 2712
2702 2713 def test_post_create_should_ignore_non_safe_attributes
2703 2714 @request.session[:user_id] = 2
2704 2715 assert_nothing_raised do
2705 2716 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
2706 2717 end
2707 2718 end
2708 2719
2709 2720 def test_post_create_with_attachment
2710 2721 set_tmp_attachments_directory
2711 2722 @request.session[:user_id] = 2
2712 2723
2713 2724 assert_difference 'Issue.count' do
2714 2725 assert_difference 'Attachment.count' do
2715 2726 assert_no_difference 'Journal.count' do
2716 2727 post :create, :project_id => 1,
2717 2728 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2718 2729 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2719 2730 end
2720 2731 end
2721 2732 end
2722 2733
2723 2734 issue = Issue.order('id DESC').first
2724 2735 attachment = Attachment.order('id DESC').first
2725 2736
2726 2737 assert_equal issue, attachment.container
2727 2738 assert_equal 2, attachment.author_id
2728 2739 assert_equal 'testfile.txt', attachment.filename
2729 2740 assert_equal 'text/plain', attachment.content_type
2730 2741 assert_equal 'test file', attachment.description
2731 2742 assert_equal 59, attachment.filesize
2732 2743 assert File.exists?(attachment.diskfile)
2733 2744 assert_equal 59, File.size(attachment.diskfile)
2734 2745 end
2735 2746
2736 2747 def test_post_create_with_attachment_should_notify_with_attachments
2737 2748 ActionMailer::Base.deliveries.clear
2738 2749 set_tmp_attachments_directory
2739 2750 @request.session[:user_id] = 2
2740 2751
2741 2752 with_settings :notified_events => %w(issue_added) do
2742 2753 assert_difference 'Issue.count' do
2743 2754 post :create, :project_id => 1,
2744 2755 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2745 2756 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2746 2757 end
2747 2758 end
2748 2759
2749 2760 assert_not_nil ActionMailer::Base.deliveries.last
2750 2761 assert_select_email do
2751 2762 assert_select 'a[href^=?]', 'http://localhost:3000/attachments/download', 'testfile.txt'
2752 2763 end
2753 2764 end
2754 2765
2755 2766 def test_post_create_with_failure_should_save_attachments
2756 2767 set_tmp_attachments_directory
2757 2768 @request.session[:user_id] = 2
2758 2769
2759 2770 assert_no_difference 'Issue.count' do
2760 2771 assert_difference 'Attachment.count' do
2761 2772 post :create, :project_id => 1,
2762 2773 :issue => { :tracker_id => '1', :subject => '' },
2763 2774 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2764 2775 assert_response :success
2765 2776 assert_template 'new'
2766 2777 end
2767 2778 end
2768 2779
2769 2780 attachment = Attachment.order('id DESC').first
2770 2781 assert_equal 'testfile.txt', attachment.filename
2771 2782 assert File.exists?(attachment.diskfile)
2772 2783 assert_nil attachment.container
2773 2784
2774 2785 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2775 2786 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2776 2787 end
2777 2788
2778 2789 def test_post_create_with_failure_should_keep_saved_attachments
2779 2790 set_tmp_attachments_directory
2780 2791 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2781 2792 @request.session[:user_id] = 2
2782 2793
2783 2794 assert_no_difference 'Issue.count' do
2784 2795 assert_no_difference 'Attachment.count' do
2785 2796 post :create, :project_id => 1,
2786 2797 :issue => { :tracker_id => '1', :subject => '' },
2787 2798 :attachments => {'p0' => {'token' => attachment.token}}
2788 2799 assert_response :success
2789 2800 assert_template 'new'
2790 2801 end
2791 2802 end
2792 2803
2793 2804 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2794 2805 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2795 2806 end
2796 2807
2797 2808 def test_post_create_should_attach_saved_attachments
2798 2809 set_tmp_attachments_directory
2799 2810 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2800 2811 @request.session[:user_id] = 2
2801 2812
2802 2813 assert_difference 'Issue.count' do
2803 2814 assert_no_difference 'Attachment.count' do
2804 2815 post :create, :project_id => 1,
2805 2816 :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
2806 2817 :attachments => {'p0' => {'token' => attachment.token}}
2807 2818 assert_response 302
2808 2819 end
2809 2820 end
2810 2821
2811 2822 issue = Issue.order('id DESC').first
2812 2823 assert_equal 1, issue.attachments.count
2813 2824
2814 2825 attachment.reload
2815 2826 assert_equal issue, attachment.container
2816 2827 end
2817 2828
2818 2829 def setup_without_workflow_privilege
2819 2830 WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
2820 2831 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2821 2832 end
2822 2833 private :setup_without_workflow_privilege
2823 2834
2824 2835 test "without workflow privilege #new should propose default status only" do
2825 2836 setup_without_workflow_privilege
2826 2837 get :new, :project_id => 1
2827 2838 assert_response :success
2828 2839 assert_template 'new'
2829 2840
2830 2841 issue = assigns(:issue)
2831 2842 assert_not_nil issue.default_status
2832 2843
2833 2844 assert_select 'select[name=?]', 'issue[status_id]' do
2834 2845 assert_select 'option', 1
2835 2846 assert_select 'option[value=?]', issue.default_status.id.to_s
2836 2847 end
2837 2848 end
2838 2849
2839 2850 test "without workflow privilege #create should accept default status" do
2840 2851 setup_without_workflow_privilege
2841 2852 assert_difference 'Issue.count' do
2842 2853 post :create, :project_id => 1,
2843 2854 :issue => {:tracker_id => 1,
2844 2855 :subject => 'This is an issue',
2845 2856 :status_id => 1}
2846 2857 end
2847 2858 issue = Issue.order('id').last
2848 2859 assert_not_nil issue.default_status
2849 2860 assert_equal issue.default_status, issue.status
2850 2861 end
2851 2862
2852 2863 test "without workflow privilege #create should ignore unauthorized status" do
2853 2864 setup_without_workflow_privilege
2854 2865 assert_difference 'Issue.count' do
2855 2866 post :create, :project_id => 1,
2856 2867 :issue => {:tracker_id => 1,
2857 2868 :subject => 'This is an issue',
2858 2869 :status_id => 3}
2859 2870 end
2860 2871 issue = Issue.order('id').last
2861 2872 assert_not_nil issue.default_status
2862 2873 assert_equal issue.default_status, issue.status
2863 2874 end
2864 2875
2865 2876 test "without workflow privilege #update should ignore status change" do
2866 2877 setup_without_workflow_privilege
2867 2878 assert_difference 'Journal.count' do
2868 2879 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2869 2880 end
2870 2881 assert_equal 1, Issue.find(1).status_id
2871 2882 end
2872 2883
2873 2884 test "without workflow privilege #update ignore attributes changes" do
2874 2885 setup_without_workflow_privilege
2875 2886 assert_difference 'Journal.count' do
2876 2887 put :update, :id => 1,
2877 2888 :issue => {:subject => 'changed', :assigned_to_id => 2,
2878 2889 :notes => 'just trying'}
2879 2890 end
2880 2891 issue = Issue.find(1)
2881 2892 assert_equal "Cannot print recipes", issue.subject
2882 2893 assert_nil issue.assigned_to
2883 2894 end
2884 2895
2885 2896 def setup_with_workflow_privilege
2886 2897 WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
2887 2898 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2888 2899 :old_status_id => 1, :new_status_id => 3)
2889 2900 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2890 2901 :old_status_id => 1, :new_status_id => 4)
2891 2902 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2892 2903 end
2893 2904 private :setup_with_workflow_privilege
2894 2905
2895 2906 def setup_with_workflow_privilege_and_edit_issues_permission
2896 2907 setup_with_workflow_privilege
2897 2908 Role.anonymous.add_permission! :add_issues, :edit_issues
2898 2909 end
2899 2910 private :setup_with_workflow_privilege_and_edit_issues_permission
2900 2911
2901 2912 test "with workflow privilege and :edit_issues permission should accept authorized status" do
2902 2913 setup_with_workflow_privilege_and_edit_issues_permission
2903 2914 assert_difference 'Journal.count' do
2904 2915 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2905 2916 end
2906 2917 assert_equal 3, Issue.find(1).status_id
2907 2918 end
2908 2919
2909 2920 test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
2910 2921 setup_with_workflow_privilege_and_edit_issues_permission
2911 2922 assert_difference 'Journal.count' do
2912 2923 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2913 2924 end
2914 2925 assert_equal 1, Issue.find(1).status_id
2915 2926 end
2916 2927
2917 2928 test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
2918 2929 setup_with_workflow_privilege_and_edit_issues_permission
2919 2930 assert_difference 'Journal.count' do
2920 2931 put :update, :id => 1,
2921 2932 :issue => {:subject => 'changed', :assigned_to_id => 2,
2922 2933 :notes => 'just trying'}
2923 2934 end
2924 2935 issue = Issue.find(1)
2925 2936 assert_equal "changed", issue.subject
2926 2937 assert_equal 2, issue.assigned_to_id
2927 2938 end
2928 2939
2929 2940 def test_new_as_copy
2930 2941 @request.session[:user_id] = 2
2931 2942 get :new, :project_id => 1, :copy_from => 1
2932 2943
2933 2944 assert_response :success
2934 2945 assert_template 'new'
2935 2946
2936 2947 assert_not_nil assigns(:issue)
2937 2948 orig = Issue.find(1)
2938 2949 assert_equal 1, assigns(:issue).project_id
2939 2950 assert_equal orig.subject, assigns(:issue).subject
2940 2951 assert assigns(:issue).copy?
2941 2952
2942 2953 assert_select 'form[id=issue-form][action="/projects/ecookbook/issues"]' do
2943 2954 assert_select 'select[name=?]', 'issue[project_id]' do
2944 2955 assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
2945 2956 assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
2946 2957 end
2947 2958 assert_select 'input[name=copy_from][value="1"]'
2948 2959 end
2949 2960 end
2950 2961
2951 2962 def test_new_as_copy_without_add_issues_permission_should_not_propose_current_project_as_target
2952 2963 user = setup_user_with_copy_but_not_add_permission
2953 2964
2954 2965 @request.session[:user_id] = user.id
2955 2966 get :new, :project_id => 1, :copy_from => 1
2956 2967
2957 2968 assert_response :success
2958 2969 assert_template 'new'
2959 2970 assert_select 'select[name=?]', 'issue[project_id]' do
2960 2971 assert_select 'option[value="1"]', 0
2961 2972 assert_select 'option[value="2"]', :text => 'OnlineStore'
2962 2973 end
2963 2974 end
2964 2975
2965 2976 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
2966 2977 @request.session[:user_id] = 2
2967 2978 issue = Issue.find(3)
2968 2979 assert issue.attachments.count > 0
2969 2980 get :new, :project_id => 1, :copy_from => 3
2970 2981
2971 2982 assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value="1"]'
2972 2983 end
2973 2984
2974 2985 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
2975 2986 @request.session[:user_id] = 2
2976 2987 issue = Issue.find(3)
2977 2988 issue.attachments.delete_all
2978 2989 get :new, :project_id => 1, :copy_from => 3
2979 2990
2980 2991 assert_select 'input[name=copy_attachments]', 0
2981 2992 end
2982 2993
2983 2994 def test_new_as_copy_should_preserve_parent_id
2984 2995 @request.session[:user_id] = 2
2985 2996 issue = Issue.generate!(:parent_issue_id => 2)
2986 2997 get :new, :project_id => 1, :copy_from => issue.id
2987 2998
2988 2999 assert_select 'input[name=?][value="2"]', 'issue[parent_issue_id]'
2989 3000 end
2990 3001
2991 3002 def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
2992 3003 @request.session[:user_id] = 2
2993 3004 issue = Issue.generate_with_descendants!
2994 3005 get :new, :project_id => 1, :copy_from => issue.id
2995 3006
2996 3007 assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value="1"]'
2997 3008 end
2998 3009
2999 3010 def test_new_as_copy_with_invalid_issue_should_respond_with_404
3000 3011 @request.session[:user_id] = 2
3001 3012 get :new, :project_id => 1, :copy_from => 99999
3002 3013 assert_response 404
3003 3014 end
3004 3015
3005 3016 def test_create_as_copy_on_different_project
3006 3017 @request.session[:user_id] = 2
3007 3018 assert_difference 'Issue.count' do
3008 3019 post :create, :project_id => 1, :copy_from => 1,
3009 3020 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
3010 3021
3011 3022 assert_not_nil assigns(:issue)
3012 3023 assert assigns(:issue).copy?
3013 3024 end
3014 3025 issue = Issue.order('id DESC').first
3015 3026 assert_redirected_to "/issues/#{issue.id}"
3016 3027
3017 3028 assert_equal 2, issue.project_id
3018 3029 assert_equal 3, issue.tracker_id
3019 3030 assert_equal 'Copy', issue.subject
3020 3031 end
3021 3032
3022 3033 def test_create_as_copy_should_allow_status_to_be_set_to_default
3023 3034 copied = Issue.generate! :status_id => 2
3024 3035 assert_equal 2, copied.reload.status_id
3025 3036
3026 3037 @request.session[:user_id] = 2
3027 3038 assert_difference 'Issue.count' do
3028 3039 post :create, :project_id => 1, :copy_from => copied.id,
3029 3040 :issue => {:project_id => '1', :tracker_id => '1', :status_id => '1'},
3030 3041 :was_default_status => '1'
3031 3042 end
3032 3043 issue = Issue.order('id DESC').first
3033 3044 assert_equal 1, issue.status_id
3034 3045 end
3035 3046
3036 3047 def test_create_as_copy_should_copy_attachments
3037 3048 @request.session[:user_id] = 2
3038 3049 issue = Issue.find(3)
3039 3050 count = issue.attachments.count
3040 3051 assert count > 0
3041 3052 assert_difference 'Issue.count' do
3042 3053 assert_difference 'Attachment.count', count do
3043 3054 post :create, :project_id => 1, :copy_from => 3,
3044 3055 :issue => {:project_id => '1', :tracker_id => '3',
3045 3056 :status_id => '1', :subject => 'Copy with attachments'},
3046 3057 :copy_attachments => '1'
3047 3058 end
3048 3059 end
3049 3060 copy = Issue.order('id DESC').first
3050 3061 assert_equal count, copy.attachments.count
3051 3062 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
3052 3063 end
3053 3064
3054 3065 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
3055 3066 @request.session[:user_id] = 2
3056 3067 issue = Issue.find(3)
3057 3068 count = issue.attachments.count
3058 3069 assert count > 0
3059 3070 assert_difference 'Issue.count' do
3060 3071 assert_no_difference 'Attachment.count' do
3061 3072 post :create, :project_id => 1, :copy_from => 3,
3062 3073 :issue => {:project_id => '1', :tracker_id => '3',
3063 3074 :status_id => '1', :subject => 'Copy with attachments'}
3064 3075 end
3065 3076 end
3066 3077 copy = Issue.order('id DESC').first
3067 3078 assert_equal 0, copy.attachments.count
3068 3079 end
3069 3080
3070 3081 def test_create_as_copy_with_attachments_should_also_add_new_files
3071 3082 @request.session[:user_id] = 2
3072 3083 issue = Issue.find(3)
3073 3084 count = issue.attachments.count
3074 3085 assert count > 0
3075 3086 assert_difference 'Issue.count' do
3076 3087 assert_difference 'Attachment.count', count + 1 do
3077 3088 post :create, :project_id => 1, :copy_from => 3,
3078 3089 :issue => {:project_id => '1', :tracker_id => '3',
3079 3090 :status_id => '1', :subject => 'Copy with attachments'},
3080 3091 :copy_attachments => '1',
3081 3092 :attachments => {'1' =>
3082 3093 {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
3083 3094 'description' => 'test file'}}
3084 3095 end
3085 3096 end
3086 3097 copy = Issue.order('id DESC').first
3087 3098 assert_equal count + 1, copy.attachments.count
3088 3099 end
3089 3100
3090 3101 def test_create_as_copy_should_add_relation_with_copied_issue
3091 3102 @request.session[:user_id] = 2
3092 3103 assert_difference 'Issue.count' do
3093 3104 assert_difference 'IssueRelation.count' do
3094 3105 post :create, :project_id => 1, :copy_from => 1, :link_copy => '1',
3095 3106 :issue => {:project_id => '1', :tracker_id => '3',
3096 3107 :status_id => '1', :subject => 'Copy'}
3097 3108 end
3098 3109 end
3099 3110 copy = Issue.order('id DESC').first
3100 3111 assert_equal 1, copy.relations.size
3101 3112 end
3102 3113
3103 3114 def test_create_as_copy_should_allow_not_to_add_relation_with_copied_issue
3104 3115 @request.session[:user_id] = 2
3105 3116 assert_difference 'Issue.count' do
3106 3117 assert_no_difference 'IssueRelation.count' do
3107 3118 post :create, :project_id => 1, :copy_from => 1,
3108 3119 :issue => {:subject => 'Copy'}
3109 3120 end
3110 3121 end
3111 3122 end
3112 3123
3113 3124 def test_create_as_copy_should_always_add_relation_with_copied_issue_by_setting
3114 3125 with_settings :link_copied_issue => 'yes' do
3115 3126 @request.session[:user_id] = 2
3116 3127 assert_difference 'Issue.count' do
3117 3128 assert_difference 'IssueRelation.count' do
3118 3129 post :create, :project_id => 1, :copy_from => 1,
3119 3130 :issue => {:subject => 'Copy'}
3120 3131 end
3121 3132 end
3122 3133 end
3123 3134 end
3124 3135
3125 3136 def test_create_as_copy_should_never_add_relation_with_copied_issue_by_setting
3126 3137 with_settings :link_copied_issue => 'no' do
3127 3138 @request.session[:user_id] = 2
3128 3139 assert_difference 'Issue.count' do
3129 3140 assert_no_difference 'IssueRelation.count' do
3130 3141 post :create, :project_id => 1, :copy_from => 1, :link_copy => '1',
3131 3142 :issue => {:subject => 'Copy'}
3132 3143 end
3133 3144 end
3134 3145 end
3135 3146 end
3136 3147
3137 3148 def test_create_as_copy_should_copy_subtasks
3138 3149 @request.session[:user_id] = 2
3139 3150 issue = Issue.generate_with_descendants!
3140 3151 count = issue.descendants.count
3141 3152 assert_difference 'Issue.count', count + 1 do
3142 3153 post :create, :project_id => 1, :copy_from => issue.id,
3143 3154 :issue => {:project_id => '1', :tracker_id => '3',
3144 3155 :status_id => '1', :subject => 'Copy with subtasks'},
3145 3156 :copy_subtasks => '1'
3146 3157 end
3147 3158 copy = Issue.where(:parent_id => nil).order('id DESC').first
3148 3159 assert_equal count, copy.descendants.count
3149 3160 assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
3150 3161 end
3151 3162
3152 3163 def test_create_as_copy_to_a_different_project_should_copy_subtask_custom_fields
3153 3164 issue = Issue.generate! {|i| i.custom_field_values = {'2' => 'Foo'}}
3154 3165 child = Issue.generate!(:parent_issue_id => issue.id) {|i| i.custom_field_values = {'2' => 'Bar'}}
3155 3166 @request.session[:user_id] = 1
3156 3167
3157 3168 assert_difference 'Issue.count', 2 do
3158 3169 post :create, :project_id => 'ecookbook', :copy_from => issue.id,
3159 3170 :issue => {:project_id => '2', :tracker_id => 1, :status_id => '1',
3160 3171 :subject => 'Copy with subtasks', :custom_field_values => {'2' => 'Foo'}},
3161 3172 :copy_subtasks => '1'
3162 3173 end
3163 3174
3164 3175 child_copy, issue_copy = Issue.order(:id => :desc).limit(2).to_a
3165 3176 assert_equal 2, issue_copy.project_id
3166 3177 assert_equal 'Foo', issue_copy.custom_field_value(2)
3167 3178 assert_equal 'Bar', child_copy.custom_field_value(2)
3168 3179 end
3169 3180
3170 3181 def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
3171 3182 @request.session[:user_id] = 2
3172 3183 issue = Issue.generate_with_descendants!
3173 3184 assert_difference 'Issue.count', 1 do
3174 3185 post :create, :project_id => 1, :copy_from => 3,
3175 3186 :issue => {:project_id => '1', :tracker_id => '3',
3176 3187 :status_id => '1', :subject => 'Copy with subtasks'}
3177 3188 end
3178 3189 copy = Issue.where(:parent_id => nil).order('id DESC').first
3179 3190 assert_equal 0, copy.descendants.count
3180 3191 end
3181 3192
3182 3193 def test_create_as_copy_with_failure
3183 3194 @request.session[:user_id] = 2
3184 3195 post :create, :project_id => 1, :copy_from => 1,
3185 3196 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
3186 3197
3187 3198 assert_response :success
3188 3199 assert_template 'new'
3189 3200
3190 3201 assert_not_nil assigns(:issue)
3191 3202 assert assigns(:issue).copy?
3192 3203
3193 3204 assert_select 'form#issue-form[action="/projects/ecookbook/issues"]' do
3194 3205 assert_select 'select[name=?]', 'issue[project_id]' do
3195 3206 assert_select 'option[value="1"]:not([selected])', :text => 'eCookbook'
3196 3207 assert_select 'option[value="2"][selected=selected]', :text => 'OnlineStore'
3197 3208 end
3198 3209 assert_select 'input[name=copy_from][value="1"]'
3199 3210 end
3200 3211 end
3201 3212
3202 3213 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
3203 3214 @request.session[:user_id] = 2
3204 3215 assert !User.find(2).member_of?(Project.find(4))
3205 3216
3206 3217 assert_difference 'Issue.count' do
3207 3218 post :create, :project_id => 1, :copy_from => 1,
3208 3219 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
3209 3220 end
3210 3221 issue = Issue.order('id DESC').first
3211 3222 assert_equal 1, issue.project_id
3212 3223 end
3213 3224
3214 3225 def test_get_edit
3215 3226 @request.session[:user_id] = 2
3216 3227 get :edit, :id => 1
3217 3228 assert_response :success
3218 3229 assert_template 'edit'
3219 3230 assert_not_nil assigns(:issue)
3220 3231 assert_equal Issue.find(1), assigns(:issue)
3221 3232
3222 3233 # Be sure we don't display inactive IssuePriorities
3223 3234 assert ! IssuePriority.find(15).active?
3224 3235 assert_select 'select[name=?]', 'issue[priority_id]' do
3225 3236 assert_select 'option[value="15"]', 0
3226 3237 end
3227 3238 end
3228 3239
3229 3240 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
3230 3241 @request.session[:user_id] = 2
3231 3242 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
3232 3243
3233 3244 get :edit, :id => 1
3234 3245 assert_select 'input[name=?]', 'time_entry[hours]'
3235 3246 end
3236 3247
3237 3248 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
3238 3249 @request.session[:user_id] = 2
3239 3250 Role.find_by_name('Manager').remove_permission! :log_time
3240 3251
3241 3252 get :edit, :id => 1
3242 3253 assert_select 'input[name=?]', 'time_entry[hours]', 0
3243 3254 end
3244 3255
3245 3256 def test_get_edit_with_params
3246 3257 @request.session[:user_id] = 2
3247 3258 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
3248 3259 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
3249 3260 assert_response :success
3250 3261 assert_template 'edit'
3251 3262
3252 3263 issue = assigns(:issue)
3253 3264 assert_not_nil issue
3254 3265
3255 3266 assert_equal 5, issue.status_id
3256 3267 assert_select 'select[name=?]', 'issue[status_id]' do
3257 3268 assert_select 'option[value="5"][selected=selected]', :text => 'Closed'
3258 3269 end
3259 3270
3260 3271 assert_equal 7, issue.priority_id
3261 3272 assert_select 'select[name=?]', 'issue[priority_id]' do
3262 3273 assert_select 'option[value="7"][selected=selected]', :text => 'Urgent'
3263 3274 end
3264 3275
3265 3276 assert_select 'input[name=?][value="2.5"]', 'time_entry[hours]'
3266 3277 assert_select 'select[name=?]', 'time_entry[activity_id]' do
3267 3278 assert_select 'option[value="10"][selected=selected]', :text => 'Development'
3268 3279 end
3269 3280 assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
3270 3281 end
3271 3282
3272 3283 def test_get_edit_with_multi_custom_field
3273 3284 field = CustomField.find(1)
3274 3285 field.update_attribute :multiple, true
3275 3286 issue = Issue.find(1)
3276 3287 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
3277 3288 issue.save!
3278 3289
3279 3290 @request.session[:user_id] = 2
3280 3291 get :edit, :id => 1
3281 3292 assert_response :success
3282 3293 assert_template 'edit'
3283 3294
3284 3295 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
3285 3296 assert_select 'option', 3
3286 3297 assert_select 'option[value=MySQL][selected=selected]'
3287 3298 assert_select 'option[value=Oracle][selected=selected]'
3288 3299 assert_select 'option[value=PostgreSQL]:not([selected])'
3289 3300 end
3290 3301 end
3291 3302
3292 3303 def test_update_form_for_existing_issue
3293 3304 @request.session[:user_id] = 2
3294 3305 xhr :patch, :edit, :id => 1,
3295 3306 :issue => {:tracker_id => 2,
3296 3307 :subject => 'This is the test_new issue',
3297 3308 :description => 'This is the description',
3298 3309 :priority_id => 5}
3299 3310 assert_response :success
3300 3311 assert_equal 'text/javascript', response.content_type
3301 3312 assert_template 'edit'
3302 3313 assert_template :partial => '_form'
3303 3314
3304 3315 issue = assigns(:issue)
3305 3316 assert_kind_of Issue, issue
3306 3317 assert_equal 1, issue.id
3307 3318 assert_equal 1, issue.project_id
3308 3319 assert_equal 2, issue.tracker_id
3309 3320 assert_equal 'This is the test_new issue', issue.subject
3310 3321 end
3311 3322
3312 3323 def test_update_form_for_existing_issue_should_keep_issue_author
3313 3324 @request.session[:user_id] = 3
3314 3325 xhr :patch, :edit, :id => 1, :issue => {:subject => 'Changed'}
3315 3326 assert_response :success
3316 3327 assert_equal 'text/javascript', response.content_type
3317 3328
3318 3329 issue = assigns(:issue)
3319 3330 assert_equal User.find(2), issue.author
3320 3331 assert_equal 2, issue.author_id
3321 3332 assert_not_equal User.current, issue.author
3322 3333 end
3323 3334
3324 3335 def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
3325 3336 @request.session[:user_id] = 2
3326 3337 WorkflowTransition.delete_all
3327 3338 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
3328 3339 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
3329 3340 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
3330 3341
3331 3342 xhr :patch, :edit, :id => 2,
3332 3343 :issue => {:tracker_id => 2,
3333 3344 :status_id => 5,
3334 3345 :subject => 'This is an issue'}
3335 3346
3336 3347 assert_equal 5, assigns(:issue).status_id
3337 3348 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
3338 3349 end
3339 3350
3340 3351 def test_update_form_for_existing_issue_with_project_change
3341 3352 @request.session[:user_id] = 2
3342 3353 xhr :patch, :edit, :id => 1,
3343 3354 :issue => {:project_id => 2,
3344 3355 :tracker_id => 2,
3345 3356 :subject => 'This is the test_new issue',
3346 3357 :description => 'This is the description',
3347 3358 :priority_id => 5}
3348 3359 assert_response :success
3349 3360 assert_template :partial => '_form'
3350 3361
3351 3362 issue = assigns(:issue)
3352 3363 assert_kind_of Issue, issue
3353 3364 assert_equal 1, issue.id
3354 3365 assert_equal 2, issue.project_id
3355 3366 assert_equal 2, issue.tracker_id
3356 3367 assert_equal 'This is the test_new issue', issue.subject
3357 3368 end
3358 3369
3359 3370 def test_update_form_should_keep_category_with_same_when_changing_project
3360 3371 source = Project.generate!
3361 3372 target = Project.generate!
3362 3373 source_category = IssueCategory.create!(:name => 'Foo', :project => source)
3363 3374 target_category = IssueCategory.create!(:name => 'Foo', :project => target)
3364 3375 issue = Issue.generate!(:project => source, :category => source_category)
3365 3376
3366 3377 @request.session[:user_id] = 1
3367 3378 patch :edit, :id => issue.id,
3368 3379 :issue => {:project_id => target.id, :category_id => source_category.id}
3369 3380 assert_response :success
3370 3381
3371 3382 issue = assigns(:issue)
3372 3383 assert_equal target_category, issue.category
3373 3384 end
3374 3385
3375 3386 def test_update_form_should_propose_default_status_for_existing_issue
3376 3387 @request.session[:user_id] = 2
3377 3388 WorkflowTransition.delete_all
3378 3389 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
3379 3390
3380 3391 xhr :patch, :edit, :id => 2
3381 3392 assert_response :success
3382 3393 assert_equal [2,3], assigns(:allowed_statuses).map(&:id).sort
3383 3394 end
3384 3395
3385 3396 def test_put_update_without_custom_fields_param
3386 3397 @request.session[:user_id] = 2
3387 3398
3388 3399 issue = Issue.find(1)
3389 3400 assert_equal '125', issue.custom_value_for(2).value
3390 3401
3391 3402 assert_difference('Journal.count') do
3392 3403 assert_difference('JournalDetail.count') do
3393 3404 put :update, :id => 1, :issue => {:subject => 'New subject'}
3394 3405 end
3395 3406 end
3396 3407 assert_redirected_to :action => 'show', :id => '1'
3397 3408 issue.reload
3398 3409 assert_equal 'New subject', issue.subject
3399 3410 # Make sure custom fields were not cleared
3400 3411 assert_equal '125', issue.custom_value_for(2).value
3401 3412 end
3402 3413
3403 3414 def test_put_update_with_project_change
3404 3415 @request.session[:user_id] = 2
3405 3416 ActionMailer::Base.deliveries.clear
3406 3417
3407 3418 with_settings :notified_events => %w(issue_updated) do
3408 3419 assert_difference('Journal.count') do
3409 3420 assert_difference('JournalDetail.count', 3) do
3410 3421 put :update, :id => 1, :issue => {:project_id => '2',
3411 3422 :tracker_id => '1', # no change
3412 3423 :priority_id => '6',
3413 3424 :category_id => '3'
3414 3425 }
3415 3426 end
3416 3427 end
3417 3428 end
3418 3429 assert_redirected_to :action => 'show', :id => '1'
3419 3430 issue = Issue.find(1)
3420 3431 assert_equal 2, issue.project_id
3421 3432 assert_equal 1, issue.tracker_id
3422 3433 assert_equal 6, issue.priority_id
3423 3434 assert_equal 3, issue.category_id
3424 3435
3425 3436 mail = ActionMailer::Base.deliveries.last
3426 3437 assert_not_nil mail
3427 3438 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
3428 3439 assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
3429 3440 end
3430 3441
3431 3442 def test_put_update_trying_to_move_issue_to_project_without_tracker_should_not_error
3432 3443 target = Project.generate!(:tracker_ids => [])
3433 3444 assert target.trackers.empty?
3434 3445 issue = Issue.generate!
3435 3446 @request.session[:user_id] = 1
3436 3447
3437 3448 put :update, :id => issue.id, :issue => {:project_id => target.id}
3438 3449 assert_response 302
3439 3450 end
3440 3451
3441 3452 def test_put_update_with_tracker_change
3442 3453 @request.session[:user_id] = 2
3443 3454 ActionMailer::Base.deliveries.clear
3444 3455
3445 3456 with_settings :notified_events => %w(issue_updated) do
3446 3457 assert_difference('Journal.count') do
3447 3458 assert_difference('JournalDetail.count', 2) do
3448 3459 put :update, :id => 1, :issue => {:project_id => '1',
3449 3460 :tracker_id => '2',
3450 3461 :priority_id => '6'
3451 3462 }
3452 3463 end
3453 3464 end
3454 3465 end
3455 3466 assert_redirected_to :action => 'show', :id => '1'
3456 3467 issue = Issue.find(1)
3457 3468 assert_equal 1, issue.project_id
3458 3469 assert_equal 2, issue.tracker_id
3459 3470 assert_equal 6, issue.priority_id
3460 3471 assert_equal 1, issue.category_id
3461 3472
3462 3473 mail = ActionMailer::Base.deliveries.last
3463 3474 assert_not_nil mail
3464 3475 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
3465 3476 assert_mail_body_match "Tracker changed from Bug to Feature request", mail
3466 3477 end
3467 3478
3468 3479 def test_put_update_with_custom_field_change
3469 3480 @request.session[:user_id] = 2
3470 3481 issue = Issue.find(1)
3471 3482 assert_equal '125', issue.custom_value_for(2).value
3472 3483
3473 3484 with_settings :notified_events => %w(issue_updated) do
3474 3485 assert_difference('Journal.count') do
3475 3486 assert_difference('JournalDetail.count', 3) do
3476 3487 put :update, :id => 1, :issue => {:subject => 'Custom field change',
3477 3488 :priority_id => '6',
3478 3489 :category_id => '1', # no change
3479 3490 :custom_field_values => { '2' => 'New custom value' }
3480 3491 }
3481 3492 end
3482 3493 end
3483 3494 end
3484 3495 assert_redirected_to :action => 'show', :id => '1'
3485 3496 issue.reload
3486 3497 assert_equal 'New custom value', issue.custom_value_for(2).value
3487 3498
3488 3499 mail = ActionMailer::Base.deliveries.last
3489 3500 assert_not_nil mail
3490 3501 assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
3491 3502 end
3492 3503
3493 3504 def test_put_update_with_multi_custom_field_change
3494 3505 field = CustomField.find(1)
3495 3506 field.update_attribute :multiple, true
3496 3507 issue = Issue.find(1)
3497 3508 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
3498 3509 issue.save!
3499 3510
3500 3511 @request.session[:user_id] = 2
3501 3512 assert_difference('Journal.count') do
3502 3513 assert_difference('JournalDetail.count', 3) do
3503 3514 put :update, :id => 1,
3504 3515 :issue => {
3505 3516 :subject => 'Custom field change',
3506 3517 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
3507 3518 }
3508 3519 end
3509 3520 end
3510 3521 assert_redirected_to :action => 'show', :id => '1'
3511 3522 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
3512 3523 end
3513 3524
3514 3525 def test_put_update_with_status_and_assignee_change
3515 3526 issue = Issue.find(1)
3516 3527 assert_equal 1, issue.status_id
3517 3528 @request.session[:user_id] = 2
3518 3529
3519 3530 with_settings :notified_events => %w(issue_updated) do
3520 3531 assert_difference('TimeEntry.count', 0) do
3521 3532 put :update,
3522 3533 :id => 1,
3523 3534 :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
3524 3535 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
3525 3536 end
3526 3537 end
3527 3538 assert_redirected_to :action => 'show', :id => '1'
3528 3539 issue.reload
3529 3540 assert_equal 2, issue.status_id
3530 3541 j = Journal.order('id DESC').first
3531 3542 assert_equal 'Assigned to dlopper', j.notes
3532 3543 assert_equal 2, j.details.size
3533 3544
3534 3545 mail = ActionMailer::Base.deliveries.last
3535 3546 assert_mail_body_match "Status changed from New to Assigned", mail
3536 3547 # subject should contain the new status
3537 3548 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
3538 3549 end
3539 3550
3540 3551 def test_put_update_with_note_only
3541 3552 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
3542 3553
3543 3554 with_settings :notified_events => %w(issue_updated) do
3544 3555 # anonymous user
3545 3556 put :update,
3546 3557 :id => 1,
3547 3558 :issue => { :notes => notes }
3548 3559 end
3549 3560 assert_redirected_to :action => 'show', :id => '1'
3550 3561 j = Journal.order('id DESC').first
3551 3562 assert_equal notes, j.notes
3552 3563 assert_equal 0, j.details.size
3553 3564 assert_equal User.anonymous, j.user
3554 3565
3555 3566 mail = ActionMailer::Base.deliveries.last
3556 3567 assert_mail_body_match notes, mail
3557 3568 end
3558 3569
3559 3570 def test_put_update_with_private_note_only
3560 3571 notes = 'Private note'
3561 3572 @request.session[:user_id] = 2
3562 3573
3563 3574 assert_difference 'Journal.count' do
3564 3575 put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
3565 3576 assert_redirected_to :action => 'show', :id => '1'
3566 3577 end
3567 3578
3568 3579 j = Journal.order('id DESC').first
3569 3580 assert_equal notes, j.notes
3570 3581 assert_equal true, j.private_notes
3571 3582 end
3572 3583
3573 3584 def test_put_update_with_private_note_and_changes
3574 3585 notes = 'Private note'
3575 3586 @request.session[:user_id] = 2
3576 3587
3577 3588 assert_difference 'Journal.count', 2 do
3578 3589 put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
3579 3590 assert_redirected_to :action => 'show', :id => '1'
3580 3591 end
3581 3592
3582 3593 j = Journal.order('id DESC').first
3583 3594 assert_equal notes, j.notes
3584 3595 assert_equal true, j.private_notes
3585 3596 assert_equal 0, j.details.count
3586 3597
3587 3598 j = Journal.order('id DESC').offset(1).first
3588 3599 assert_nil j.notes
3589 3600 assert_equal false, j.private_notes
3590 3601 assert_equal 1, j.details.count
3591 3602 end
3592 3603
3593 3604 def test_put_update_with_note_and_spent_time
3594 3605 @request.session[:user_id] = 2
3595 3606 spent_hours_before = Issue.find(1).spent_hours
3596 3607 assert_difference('TimeEntry.count') do
3597 3608 put :update,
3598 3609 :id => 1,
3599 3610 :issue => { :notes => '2.5 hours added' },
3600 3611 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
3601 3612 end
3602 3613 assert_redirected_to :action => 'show', :id => '1'
3603 3614
3604 3615 issue = Issue.find(1)
3605 3616
3606 3617 j = Journal.order('id DESC').first
3607 3618 assert_equal '2.5 hours added', j.notes
3608 3619 assert_equal 0, j.details.size
3609 3620
3610 3621 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
3611 3622 assert_not_nil t
3612 3623 assert_equal 2.5, t.hours
3613 3624 assert_equal spent_hours_before + 2.5, issue.spent_hours
3614 3625 end
3615 3626
3616 3627 def test_put_update_should_preserve_parent_issue_even_if_not_visible
3617 3628 parent = Issue.generate!(:project_id => 1, :is_private => true)
3618 3629 issue = Issue.generate!(:parent_issue_id => parent.id)
3619 3630 assert !parent.visible?(User.find(3))
3620 3631 @request.session[:user_id] = 3
3621 3632
3622 3633 get :edit, :id => issue.id
3623 3634 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
3624 3635
3625 3636 put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
3626 3637 assert_response 302
3627 3638 assert_equal parent, issue.parent
3628 3639 end
3629 3640
3630 3641 def test_put_update_with_attachment_only
3631 3642 set_tmp_attachments_directory
3632 3643
3633 3644 # Delete all fixtured journals, a race condition can occur causing the wrong
3634 3645 # journal to get fetched in the next find.
3635 3646 Journal.delete_all
3636 3647
3637 3648 with_settings :notified_events => %w(issue_updated) do
3638 3649 # anonymous user
3639 3650 assert_difference 'Attachment.count' do
3640 3651 put :update, :id => 1,
3641 3652 :issue => {:notes => ''},
3642 3653 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3643 3654 end
3644 3655 end
3645 3656
3646 3657 assert_redirected_to :action => 'show', :id => '1'
3647 3658 j = Issue.find(1).journals.reorder('id DESC').first
3648 3659 assert j.notes.blank?
3649 3660 assert_equal 1, j.details.size
3650 3661 assert_equal 'testfile.txt', j.details.first.value
3651 3662 assert_equal User.anonymous, j.user
3652 3663
3653 3664 attachment = Attachment.order('id DESC').first
3654 3665 assert_equal Issue.find(1), attachment.container
3655 3666 assert_equal User.anonymous, attachment.author
3656 3667 assert_equal 'testfile.txt', attachment.filename
3657 3668 assert_equal 'text/plain', attachment.content_type
3658 3669 assert_equal 'test file', attachment.description
3659 3670 assert_equal 59, attachment.filesize
3660 3671 assert File.exists?(attachment.diskfile)
3661 3672 assert_equal 59, File.size(attachment.diskfile)
3662 3673
3663 3674 mail = ActionMailer::Base.deliveries.last
3664 3675 assert_mail_body_match 'testfile.txt', mail
3665 3676 end
3666 3677
3667 3678 def test_put_update_with_failure_should_save_attachments
3668 3679 set_tmp_attachments_directory
3669 3680 @request.session[:user_id] = 2
3670 3681
3671 3682 assert_no_difference 'Journal.count' do
3672 3683 assert_difference 'Attachment.count' do
3673 3684 put :update, :id => 1,
3674 3685 :issue => { :subject => '' },
3675 3686 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3676 3687 assert_response :success
3677 3688 assert_template 'edit'
3678 3689 end
3679 3690 end
3680 3691
3681 3692 attachment = Attachment.order('id DESC').first
3682 3693 assert_equal 'testfile.txt', attachment.filename
3683 3694 assert File.exists?(attachment.diskfile)
3684 3695 assert_nil attachment.container
3685 3696
3686 3697 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3687 3698 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3688 3699 end
3689 3700
3690 3701 def test_put_update_with_failure_should_keep_saved_attachments
3691 3702 set_tmp_attachments_directory
3692 3703 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3693 3704 @request.session[:user_id] = 2
3694 3705
3695 3706 assert_no_difference 'Journal.count' do
3696 3707 assert_no_difference 'Attachment.count' do
3697 3708 put :update, :id => 1,
3698 3709 :issue => { :subject => '' },
3699 3710 :attachments => {'p0' => {'token' => attachment.token}}
3700 3711 assert_response :success
3701 3712 assert_template 'edit'
3702 3713 end
3703 3714 end
3704 3715
3705 3716 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3706 3717 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3707 3718 end
3708 3719
3709 3720 def test_put_update_should_attach_saved_attachments
3710 3721 set_tmp_attachments_directory
3711 3722 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3712 3723 @request.session[:user_id] = 2
3713 3724
3714 3725 assert_difference 'Journal.count' do
3715 3726 assert_difference 'JournalDetail.count' do
3716 3727 assert_no_difference 'Attachment.count' do
3717 3728 put :update, :id => 1,
3718 3729 :issue => {:notes => 'Attachment added'},
3719 3730 :attachments => {'p0' => {'token' => attachment.token}}
3720 3731 assert_redirected_to '/issues/1'
3721 3732 end
3722 3733 end
3723 3734 end
3724 3735
3725 3736 attachment.reload
3726 3737 assert_equal Issue.find(1), attachment.container
3727 3738
3728 3739 journal = Journal.order('id DESC').first
3729 3740 assert_equal 1, journal.details.size
3730 3741 assert_equal 'testfile.txt', journal.details.first.value
3731 3742 end
3732 3743
3733 3744 def test_put_update_with_attachment_that_fails_to_save
3734 3745 set_tmp_attachments_directory
3735 3746
3736 3747 # anonymous user
3737 3748 with_settings :attachment_max_size => 0 do
3738 3749 put :update,
3739 3750 :id => 1,
3740 3751 :issue => {:notes => ''},
3741 3752 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
3742 3753 assert_redirected_to :action => 'show', :id => '1'
3743 3754 assert_equal '1 file(s) could not be saved.', flash[:warning]
3744 3755 end
3745 3756 end
3746 3757
3747 3758 def test_put_update_with_no_change
3748 3759 issue = Issue.find(1)
3749 3760 issue.journals.clear
3750 3761 ActionMailer::Base.deliveries.clear
3751 3762
3752 3763 put :update,
3753 3764 :id => 1,
3754 3765 :issue => {:notes => ''}
3755 3766 assert_redirected_to :action => 'show', :id => '1'
3756 3767
3757 3768 issue.reload
3758 3769 assert issue.journals.empty?
3759 3770 # No email should be sent
3760 3771 assert ActionMailer::Base.deliveries.empty?
3761 3772 end
3762 3773
3763 3774 def test_put_update_should_send_a_notification
3764 3775 @request.session[:user_id] = 2
3765 3776 ActionMailer::Base.deliveries.clear
3766 3777 issue = Issue.find(1)
3767 3778 old_subject = issue.subject
3768 3779 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
3769 3780
3770 3781 with_settings :notified_events => %w(issue_updated) do
3771 3782 put :update, :id => 1, :issue => {:subject => new_subject,
3772 3783 :priority_id => '6',
3773 3784 :category_id => '1' # no change
3774 3785 }
3775 3786 assert_equal 1, ActionMailer::Base.deliveries.size
3776 3787 end
3777 3788 end
3778 3789
3779 3790 def test_put_update_with_invalid_spent_time_hours_only
3780 3791 @request.session[:user_id] = 2
3781 3792 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3782 3793
3783 3794 assert_no_difference('Journal.count') do
3784 3795 put :update,
3785 3796 :id => 1,
3786 3797 :issue => {:notes => notes},
3787 3798 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
3788 3799 end
3789 3800 assert_response :success
3790 3801 assert_template 'edit'
3791 3802
3792 3803 assert_select_error /Activity cannot be blank/
3793 3804 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3794 3805 assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
3795 3806 end
3796 3807
3797 3808 def test_put_update_with_invalid_spent_time_comments_only
3798 3809 @request.session[:user_id] = 2
3799 3810 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3800 3811
3801 3812 assert_no_difference('Journal.count') do
3802 3813 put :update,
3803 3814 :id => 1,
3804 3815 :issue => {:notes => notes},
3805 3816 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
3806 3817 end
3807 3818 assert_response :success
3808 3819 assert_template 'edit'
3809 3820
3810 3821 assert_select_error /Activity cannot be blank/
3811 3822 assert_select_error /Hours cannot be blank/
3812 3823 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3813 3824 assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
3814 3825 end
3815 3826
3816 3827 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
3817 3828 issue = Issue.find(2)
3818 3829 @request.session[:user_id] = 2
3819 3830
3820 3831 put :update,
3821 3832 :id => issue.id,
3822 3833 :issue => {
3823 3834 :fixed_version_id => 4
3824 3835 }
3825 3836
3826 3837 assert_response :redirect
3827 3838 issue.reload
3828 3839 assert_equal 4, issue.fixed_version_id
3829 3840 assert_not_equal issue.project_id, issue.fixed_version.project_id
3830 3841 end
3831 3842
3832 3843 def test_put_update_should_redirect_back_using_the_back_url_parameter
3833 3844 issue = Issue.find(2)
3834 3845 @request.session[:user_id] = 2
3835 3846
3836 3847 put :update,
3837 3848 :id => issue.id,
3838 3849 :issue => {
3839 3850 :fixed_version_id => 4
3840 3851 },
3841 3852 :back_url => '/issues'
3842 3853
3843 3854 assert_response :redirect
3844 3855 assert_redirected_to '/issues'
3845 3856 end
3846 3857
3847 3858 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3848 3859 issue = Issue.find(2)
3849 3860 @request.session[:user_id] = 2
3850 3861
3851 3862 put :update,
3852 3863 :id => issue.id,
3853 3864 :issue => {
3854 3865 :fixed_version_id => 4
3855 3866 },
3856 3867 :back_url => 'http://google.com'
3857 3868
3858 3869 assert_response :redirect
3859 3870 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3860 3871 end
3861 3872
3862 3873 def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
3863 3874 @request.session[:user_id] = 2
3864 3875
3865 3876 put :update, :id => 11,
3866 3877 :issue => {:status_id => 6, :notes => 'Notes'},
3867 3878 :prev_issue_id => 8,
3868 3879 :next_issue_id => 12,
3869 3880 :issue_position => 2,
3870 3881 :issue_count => 3
3871 3882
3872 3883 assert_redirected_to '/issues/11?issue_count=3&issue_position=2&next_issue_id=12&prev_issue_id=8'
3873 3884 end
3874 3885
3875 3886 def test_update_with_permission_on_tracker_should_be_allowed
3876 3887 role = Role.find(1)
3877 3888 role.set_permission_trackers :edit_issues, [1]
3878 3889 role.save!
3879 3890 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Original subject')
3880 3891
3881 3892 @request.session[:user_id] = 2
3882 3893 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3883 3894 assert_response 302
3884 3895 assert_equal 'Changed subject', issue.reload.subject
3885 3896 end
3886 3897
3887 3898 def test_update_without_permission_on_tracker_should_be_denied
3888 3899 role = Role.find(1)
3889 3900 role.set_permission_trackers :edit_issues, [1]
3890 3901 role.save!
3891 3902 issue = Issue.generate!(:project_id => 1, :tracker_id => 2, :subject => 'Original subject')
3892 3903
3893 3904 @request.session[:user_id] = 2
3894 3905 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3895 3906 assert_response 302
3896 3907 assert_equal 'Original subject', issue.reload.subject
3897 3908 end
3898 3909
3899 3910 def test_get_bulk_edit
3900 3911 @request.session[:user_id] = 2
3901 3912 get :bulk_edit, :ids => [1, 3]
3902 3913 assert_response :success
3903 3914 assert_template 'bulk_edit'
3904 3915
3905 3916 assert_select 'ul#bulk-selection' do
3906 3917 assert_select 'li', 2
3907 3918 assert_select 'li a', :text => 'Bug #1'
3908 3919 end
3909 3920
3910 3921 assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
3911 3922 assert_select 'input[name=?]', 'ids[]', 2
3912 3923 assert_select 'input[name=?][value="1"][type=hidden]', 'ids[]'
3913 3924
3914 3925 assert_select 'select[name=?]', 'issue[project_id]'
3915 3926 assert_select 'input[name=?]', 'issue[parent_issue_id]'
3916 3927
3917 3928 # Project specific custom field, date type
3918 3929 field = CustomField.find(9)
3919 3930 assert !field.is_for_all?
3920 3931 assert_equal 'date', field.field_format
3921 3932 assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3922 3933
3923 3934 # System wide custom field
3924 3935 assert CustomField.find(1).is_for_all?
3925 3936 assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3926 3937
3927 3938 # Be sure we don't display inactive IssuePriorities
3928 3939 assert ! IssuePriority.find(15).active?
3929 3940 assert_select 'select[name=?]', 'issue[priority_id]' do
3930 3941 assert_select 'option[value="15"]', 0
3931 3942 end
3932 3943 end
3933 3944 end
3934 3945
3935 3946 def test_get_bulk_edit_on_different_projects
3936 3947 @request.session[:user_id] = 2
3937 3948 get :bulk_edit, :ids => [1, 2, 6]
3938 3949 assert_response :success
3939 3950 assert_template 'bulk_edit'
3940 3951
3941 3952 # Can not set issues from different projects as children of an issue
3942 3953 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
3943 3954
3944 3955 # Project specific custom field, date type
3945 3956 field = CustomField.find(9)
3946 3957 assert !field.is_for_all?
3947 3958 assert !field.project_ids.include?(Issue.find(6).project_id)
3948 3959 assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
3949 3960 end
3950 3961
3951 3962 def test_get_bulk_edit_with_user_custom_field
3952 3963 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true, :tracker_ids => [1,2,3])
3953 3964
3954 3965 @request.session[:user_id] = 2
3955 3966 get :bulk_edit, :ids => [1, 2]
3956 3967 assert_response :success
3957 3968 assert_template 'bulk_edit'
3958 3969
3959 3970 assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3960 3971 assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
3961 3972 end
3962 3973 end
3963 3974
3964 3975 def test_get_bulk_edit_with_version_custom_field
3965 3976 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
3966 3977
3967 3978 @request.session[:user_id] = 2
3968 3979 get :bulk_edit, :ids => [1, 2]
3969 3980 assert_response :success
3970 3981 assert_template 'bulk_edit'
3971 3982
3972 3983 assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3973 3984 assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
3974 3985 end
3975 3986 end
3976 3987
3977 3988 def test_get_bulk_edit_with_multi_custom_field
3978 3989 field = CustomField.find(1)
3979 3990 field.update_attribute :multiple, true
3980 3991
3981 3992 @request.session[:user_id] = 2
3982 3993 get :bulk_edit, :ids => [1, 3]
3983 3994 assert_response :success
3984 3995 assert_template 'bulk_edit'
3985 3996
3986 3997 assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
3987 3998 assert_select 'option', field.possible_values.size + 1 # "none" options
3988 3999 end
3989 4000 end
3990 4001
3991 4002 def test_bulk_edit_should_propose_to_clear_text_custom_fields
3992 4003 @request.session[:user_id] = 2
3993 4004 get :bulk_edit, :ids => [1, 3]
3994 4005 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
3995 4006 end
3996 4007
3997 4008 def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
3998 4009 WorkflowTransition.delete_all
3999 4010 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
4000 4011 :old_status_id => 1, :new_status_id => 1)
4001 4012 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
4002 4013 :old_status_id => 1, :new_status_id => 3)
4003 4014 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
4004 4015 :old_status_id => 1, :new_status_id => 4)
4005 4016 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
4006 4017 :old_status_id => 2, :new_status_id => 1)
4007 4018 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
4008 4019 :old_status_id => 2, :new_status_id => 3)
4009 4020 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
4010 4021 :old_status_id => 2, :new_status_id => 5)
4011 4022 @request.session[:user_id] = 2
4012 4023 get :bulk_edit, :ids => [1, 2]
4013 4024
4014 4025 assert_response :success
4015 4026 statuses = assigns(:available_statuses)
4016 4027 assert_not_nil statuses
4017 4028 assert_equal [1, 3], statuses.map(&:id).sort
4018 4029
4019 4030 assert_select 'select[name=?]', 'issue[status_id]' do
4020 4031 assert_select 'option', 3 # 2 statuses + "no change" option
4021 4032 end
4022 4033 end
4023 4034
4024 4035 def test_bulk_edit_should_propose_target_project_open_shared_versions
4025 4036 @request.session[:user_id] = 2
4026 4037 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
4027 4038 assert_response :success
4028 4039 assert_template 'bulk_edit'
4029 4040 assert_equal Project.find(1).shared_versions.open.to_a.sort, assigns(:versions).sort
4030 4041
4031 4042 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
4032 4043 assert_select 'option', :text => '2.0'
4033 4044 end
4034 4045 end
4035 4046
4036 4047 def test_bulk_edit_should_propose_target_project_categories
4037 4048 @request.session[:user_id] = 2
4038 4049 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
4039 4050 assert_response :success
4040 4051 assert_template 'bulk_edit'
4041 4052 assert_equal Project.find(1).issue_categories.sort, assigns(:categories).sort
4042 4053
4043 4054 assert_select 'select[name=?]', 'issue[category_id]' do
4044 4055 assert_select 'option', :text => 'Recipes'
4045 4056 end
4046 4057 end
4047 4058
4048 4059 def test_bulk_edit_should_only_propose_issues_trackers_custom_fields
4049 4060 IssueCustomField.delete_all
4050 4061 field = IssueCustomField.generate!(:tracker_ids => [1], :is_for_all => true)
4051 4062 IssueCustomField.generate!(:tracker_ids => [2], :is_for_all => true)
4052 4063 @request.session[:user_id] = 2
4053 4064
4054 4065 issue_ids = Issue.where(:project_id => 1, :tracker_id => 1).limit(2).ids
4055 4066 get :bulk_edit, :ids => issue_ids
4056 4067 assert_equal [field], assigns(:custom_fields)
4057 4068 end
4058 4069
4059 4070 def test_bulk_update
4060 4071 @request.session[:user_id] = 2
4061 4072 # update issues priority
4062 4073 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
4063 4074 :issue => {:priority_id => 7,
4064 4075 :assigned_to_id => '',
4065 4076 :custom_field_values => {'2' => ''}}
4066 4077
4067 4078 assert_response 302
4068 4079 # check that the issues were updated
4069 4080 assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id}
4070 4081
4071 4082 issue = Issue.find(1)
4072 4083 journal = issue.journals.reorder('created_on DESC').first
4073 4084 assert_equal '125', issue.custom_value_for(2).value
4074 4085 assert_equal 'Bulk editing', journal.notes
4075 4086 assert_equal 1, journal.details.size
4076 4087 end
4077 4088
4078 4089 def test_bulk_update_with_group_assignee
4079 4090 group = Group.find(11)
4080 4091 project = Project.find(1)
4081 4092 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
4082 4093
4083 4094 @request.session[:user_id] = 2
4084 4095 # update issues assignee
4085 4096 with_settings :issue_group_assignment => '1' do
4086 4097 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
4087 4098 :issue => {:priority_id => '',
4088 4099 :assigned_to_id => group.id,
4089 4100 :custom_field_values => {'2' => ''}}
4090 4101
4091 4102 assert_response 302
4092 4103 assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
4093 4104 end
4094 4105 end
4095 4106
4096 4107 def test_bulk_update_on_different_projects
4097 4108 @request.session[:user_id] = 2
4098 4109 # update issues priority
4099 4110 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
4100 4111 :issue => {:priority_id => 7,
4101 4112 :assigned_to_id => '',
4102 4113 :custom_field_values => {'2' => ''}}
4103 4114
4104 4115 assert_response 302
4105 4116 # check that the issues were updated
4106 4117 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
4107 4118
4108 4119 issue = Issue.find(1)
4109 4120 journal = issue.journals.reorder('created_on DESC').first
4110 4121 assert_equal '125', issue.custom_value_for(2).value
4111 4122 assert_equal 'Bulk editing', journal.notes
4112 4123 assert_equal 1, journal.details.size
4113 4124 end
4114 4125
4115 4126 def test_bulk_update_on_different_projects_without_rights
4116 4127 @request.session[:user_id] = 3
4117 4128 user = User.find(3)
4118 4129 action = { :controller => "issues", :action => "bulk_update" }
4119 4130 assert user.allowed_to?(action, Issue.find(1).project)
4120 4131 assert ! user.allowed_to?(action, Issue.find(6).project)
4121 4132 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
4122 4133 :issue => {:priority_id => 7,
4123 4134 :assigned_to_id => '',
4124 4135 :custom_field_values => {'2' => ''}}
4125 4136 assert_response 403
4126 4137 assert_not_equal "Bulk should fail", Journal.last.notes
4127 4138 end
4128 4139
4129 4140 def test_bullk_update_should_send_a_notification
4130 4141 @request.session[:user_id] = 2
4131 4142 ActionMailer::Base.deliveries.clear
4132 4143 with_settings :notified_events => %w(issue_updated) do
4133 4144 post(:bulk_update,
4134 4145 {
4135 4146 :ids => [1, 2],
4136 4147 :notes => 'Bulk editing',
4137 4148 :issue => {
4138 4149 :priority_id => 7,
4139 4150 :assigned_to_id => '',
4140 4151 :custom_field_values => {'2' => ''}
4141 4152 }
4142 4153 })
4143 4154 assert_response 302
4144 4155 assert_equal 2, ActionMailer::Base.deliveries.size
4145 4156 end
4146 4157 end
4147 4158
4148 4159 def test_bulk_update_project
4149 4160 @request.session[:user_id] = 2
4150 4161 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
4151 4162 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4152 4163 # Issues moved to project 2
4153 4164 assert_equal 2, Issue.find(1).project_id
4154 4165 assert_equal 2, Issue.find(2).project_id
4155 4166 # No tracker change
4156 4167 assert_equal 1, Issue.find(1).tracker_id
4157 4168 assert_equal 2, Issue.find(2).tracker_id
4158 4169 end
4159 4170
4160 4171 def test_bulk_update_project_on_single_issue_should_follow_when_needed
4161 4172 @request.session[:user_id] = 2
4162 4173 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
4163 4174 assert_redirected_to '/issues/1'
4164 4175 end
4165 4176
4166 4177 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
4167 4178 @request.session[:user_id] = 2
4168 4179 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
4169 4180 assert_redirected_to '/projects/onlinestore/issues'
4170 4181 end
4171 4182
4172 4183 def test_bulk_update_tracker
4173 4184 @request.session[:user_id] = 2
4174 4185 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
4175 4186 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4176 4187 assert_equal 2, Issue.find(1).tracker_id
4177 4188 assert_equal 2, Issue.find(2).tracker_id
4178 4189 end
4179 4190
4180 4191 def test_bulk_update_status
4181 4192 @request.session[:user_id] = 2
4182 4193 # update issues priority
4183 4194 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
4184 4195 :issue => {:priority_id => '',
4185 4196 :assigned_to_id => '',
4186 4197 :status_id => '5'}
4187 4198
4188 4199 assert_response 302
4189 4200 issue = Issue.find(1)
4190 4201 assert issue.closed?
4191 4202 end
4192 4203
4193 4204 def test_bulk_update_priority
4194 4205 @request.session[:user_id] = 2
4195 4206 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
4196 4207
4197 4208 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4198 4209 assert_equal 6, Issue.find(1).priority_id
4199 4210 assert_equal 6, Issue.find(2).priority_id
4200 4211 end
4201 4212
4202 4213 def test_bulk_update_with_notes
4203 4214 @request.session[:user_id] = 2
4204 4215 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
4205 4216
4206 4217 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4207 4218 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
4208 4219 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
4209 4220 end
4210 4221
4211 4222 def test_bulk_update_parent_id
4212 4223 IssueRelation.delete_all
4213 4224 @request.session[:user_id] = 2
4214 4225 post :bulk_update, :ids => [1, 3],
4215 4226 :notes => 'Bulk editing parent',
4216 4227 :issue => {:priority_id => '', :assigned_to_id => '',
4217 4228 :status_id => '', :parent_issue_id => '2'}
4218 4229 assert_response 302
4219 4230 parent = Issue.find(2)
4220 4231 assert_equal parent.id, Issue.find(1).parent_id
4221 4232 assert_equal parent.id, Issue.find(3).parent_id
4222 4233 assert_equal [1, 3], parent.children.collect(&:id).sort
4223 4234 end
4224 4235
4225 4236 def test_bulk_update_estimated_hours
4226 4237 @request.session[:user_id] = 2
4227 4238 post :bulk_update, :ids => [1, 2], :issue => {:estimated_hours => 4.25}
4228 4239
4229 4240 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4230 4241 assert_equal 4.25, Issue.find(1).estimated_hours
4231 4242 assert_equal 4.25, Issue.find(2).estimated_hours
4232 4243 end
4233 4244
4234 4245 def test_bulk_update_custom_field
4235 4246 @request.session[:user_id] = 2
4236 4247 # update issues priority
4237 4248 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
4238 4249 :issue => {:priority_id => '',
4239 4250 :assigned_to_id => '',
4240 4251 :custom_field_values => {'2' => '777'}}
4241 4252
4242 4253 assert_response 302
4243 4254
4244 4255 issue = Issue.find(1)
4245 4256 journal = issue.journals.reorder('created_on DESC').first
4246 4257 assert_equal '777', issue.custom_value_for(2).value
4247 4258 assert_equal 1, journal.details.size
4248 4259 assert_equal '125', journal.details.first.old_value
4249 4260 assert_equal '777', journal.details.first.value
4250 4261 end
4251 4262
4252 4263 def test_bulk_update_custom_field_to_blank
4253 4264 @request.session[:user_id] = 2
4254 4265 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
4255 4266 :issue => {:priority_id => '',
4256 4267 :assigned_to_id => '',
4257 4268 :custom_field_values => {'1' => '__none__'}}
4258 4269 assert_response 302
4259 4270 assert_equal '', Issue.find(1).custom_field_value(1)
4260 4271 assert_equal '', Issue.find(3).custom_field_value(1)
4261 4272 end
4262 4273
4263 4274 def test_bulk_update_multi_custom_field
4264 4275 field = CustomField.find(1)
4265 4276 field.update_attribute :multiple, true
4266 4277
4267 4278 @request.session[:user_id] = 2
4268 4279 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
4269 4280 :issue => {:priority_id => '',
4270 4281 :assigned_to_id => '',
4271 4282 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
4272 4283
4273 4284 assert_response 302
4274 4285
4275 4286 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
4276 4287 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
4277 4288 # the custom field is not associated with the issue tracker
4278 4289 assert_nil Issue.find(2).custom_field_value(1)
4279 4290 end
4280 4291
4281 4292 def test_bulk_update_multi_custom_field_to_blank
4282 4293 field = CustomField.find(1)
4283 4294 field.update_attribute :multiple, true
4284 4295
4285 4296 @request.session[:user_id] = 2
4286 4297 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
4287 4298 :issue => {:priority_id => '',
4288 4299 :assigned_to_id => '',
4289 4300 :custom_field_values => {'1' => ['__none__']}}
4290 4301 assert_response 302
4291 4302 assert_equal [''], Issue.find(1).custom_field_value(1)
4292 4303 assert_equal [''], Issue.find(3).custom_field_value(1)
4293 4304 end
4294 4305
4295 4306 def test_bulk_update_unassign
4296 4307 assert_not_nil Issue.find(2).assigned_to
4297 4308 @request.session[:user_id] = 2
4298 4309 # unassign issues
4299 4310 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
4300 4311 assert_response 302
4301 4312 # check that the issues were updated
4302 4313 assert_nil Issue.find(2).assigned_to
4303 4314 end
4304 4315
4305 4316 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
4306 4317 @request.session[:user_id] = 2
4307 4318
4308 4319 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
4309 4320
4310 4321 assert_response :redirect
4311 4322 issues = Issue.find([1,2])
4312 4323 issues.each do |issue|
4313 4324 assert_equal 4, issue.fixed_version_id
4314 4325 assert_not_equal issue.project_id, issue.fixed_version.project_id
4315 4326 end
4316 4327 end
4317 4328
4318 4329 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
4319 4330 @request.session[:user_id] = 2
4320 4331 post :bulk_update, :ids => [1,2], :back_url => '/issues'
4321 4332
4322 4333 assert_response :redirect
4323 4334 assert_redirected_to '/issues'
4324 4335 end
4325 4336
4326 4337 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
4327 4338 @request.session[:user_id] = 2
4328 4339 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
4329 4340
4330 4341 assert_response :redirect
4331 4342 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
4332 4343 end
4333 4344
4334 4345 def test_bulk_update_with_all_failures_should_show_errors
4335 4346 @request.session[:user_id] = 2
4336 4347 post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
4337 4348
4338 4349 assert_response :success
4339 4350 assert_template 'bulk_edit'
4340 4351 assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
4341 4352 assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
4342 4353
4343 4354 assert_equal [1, 2], assigns[:issues].map(&:id)
4344 4355 end
4345 4356
4346 4357 def test_bulk_update_with_some_failures_should_show_errors
4347 4358 issue1 = Issue.generate!(:start_date => '2013-05-12')
4348 4359 issue2 = Issue.generate!(:start_date => '2013-05-15')
4349 4360 issue3 = Issue.generate!
4350 4361 @request.session[:user_id] = 2
4351 4362 post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id],
4352 4363 :issue => {:due_date => '2013-05-01'}
4353 4364 assert_response :success
4354 4365 assert_template 'bulk_edit'
4355 4366 assert_select '#errorExplanation span',
4356 4367 :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
4357 4368 assert_select '#errorExplanation ul li',
4358 4369 :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
4359 4370 assert_equal [issue1.id, issue2.id], assigns[:issues].map(&:id)
4360 4371 end
4361 4372
4362 4373 def test_bulk_update_with_failure_should_preserved_form_values
4363 4374 @request.session[:user_id] = 2
4364 4375 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2', :start_date => 'foo'}
4365 4376
4366 4377 assert_response :success
4367 4378 assert_template 'bulk_edit'
4368 4379 assert_select 'select[name=?]', 'issue[tracker_id]' do
4369 4380 assert_select 'option[value="2"][selected=selected]'
4370 4381 end
4371 4382 assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
4372 4383 end
4373 4384
4374 4385 def test_get_bulk_copy
4375 4386 @request.session[:user_id] = 2
4376 4387 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
4377 4388 assert_response :success
4378 4389 assert_template 'bulk_edit'
4379 4390
4380 4391 issues = assigns(:issues)
4381 4392 assert_not_nil issues
4382 4393 assert_equal [1, 2, 3], issues.map(&:id).sort
4383 4394
4384 4395 assert_select 'select[name=?]', 'issue[project_id]' do
4385 4396 assert_select 'option[value=""]'
4386 4397 end
4387 4398 assert_select 'input[name=copy_attachments]'
4388 4399 end
4389 4400
4390 4401 def test_get_bulk_copy_without_add_issues_permission_should_not_propose_current_project_as_target
4391 4402 user = setup_user_with_copy_but_not_add_permission
4392 4403 @request.session[:user_id] = user.id
4393 4404
4394 4405 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
4395 4406 assert_response :success
4396 4407 assert_template 'bulk_edit'
4397 4408
4398 4409 assert_select 'select[name=?]', 'issue[project_id]' do
4399 4410 assert_select 'option[value=""]', 0
4400 4411 assert_select 'option[value="2"]'
4401 4412 end
4402 4413 end
4403 4414
4404 4415 def test_bulk_copy_to_another_project
4405 4416 @request.session[:user_id] = 2
4406 4417 assert_difference 'Issue.count', 2 do
4407 4418 assert_no_difference 'Project.find(1).issues.count' do
4408 4419 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
4409 4420 end
4410 4421 end
4411 4422 assert_redirected_to '/projects/ecookbook/issues'
4412 4423
4413 4424 copies = Issue.order('id DESC').limit(issues.size)
4414 4425 copies.each do |copy|
4415 4426 assert_equal 2, copy.project_id
4416 4427 end
4417 4428 end
4418 4429
4419 4430 def test_bulk_copy_without_add_issues_permission_should_be_allowed_on_project_with_permission
4420 4431 user = setup_user_with_copy_but_not_add_permission
4421 4432 @request.session[:user_id] = user.id
4422 4433
4423 4434 assert_difference 'Issue.count', 3 do
4424 4435 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => '2'}, :copy => '1'
4425 4436 assert_response 302
4426 4437 end
4427 4438 end
4428 4439
4429 4440 def test_bulk_copy_on_same_project_without_add_issues_permission_should_be_denied
4430 4441 user = setup_user_with_copy_but_not_add_permission
4431 4442 @request.session[:user_id] = user.id
4432 4443
4433 4444 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => ''}, :copy => '1'
4434 4445 assert_response 403
4435 4446 end
4436 4447
4437 4448 def test_bulk_copy_on_different_project_without_add_issues_permission_should_be_denied
4438 4449 user = setup_user_with_copy_but_not_add_permission
4439 4450 @request.session[:user_id] = user.id
4440 4451
4441 4452 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => '1'}, :copy => '1'
4442 4453 assert_response 403
4443 4454 end
4444 4455
4445 4456 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
4446 4457 @request.session[:user_id] = 2
4447 4458 issues = [
4448 4459 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
4449 4460 :priority_id => 2, :subject => 'issue 1', :author_id => 1,
4450 4461 :assigned_to_id => nil),
4451 4462 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
4452 4463 :priority_id => 1, :subject => 'issue 2', :author_id => 2,
4453 4464 :assigned_to_id => 3)
4454 4465 ]
4455 4466 assert_difference 'Issue.count', issues.size do
4456 4467 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
4457 4468 :issue => {
4458 4469 :project_id => '', :tracker_id => '', :assigned_to_id => '',
4459 4470 :status_id => '', :start_date => '', :due_date => ''
4460 4471 }
4461 4472 end
4462 4473
4463 4474 copies = Issue.order('id DESC').limit(issues.size)
4464 4475 issues.each do |orig|
4465 4476 copy = copies.detect {|c| c.subject == orig.subject}
4466 4477 assert_not_nil copy
4467 4478 assert_equal orig.project_id, copy.project_id
4468 4479 assert_equal orig.tracker_id, copy.tracker_id
4469 4480 assert_equal orig.status_id, copy.status_id
4470 4481 assert_equal orig.assigned_to_id, copy.assigned_to_id
4471 4482 assert_equal orig.priority_id, copy.priority_id
4472 4483 end
4473 4484 end
4474 4485
4475 4486 def test_bulk_copy_should_allow_changing_the_issue_attributes
4476 4487 # Fixes random test failure with Mysql
4477 4488 # where Issue.where(:project_id => 2).limit(2).order('id desc')
4478 4489 # doesn't return the expected results
4479 4490 Issue.delete_all("project_id=2")
4480 4491
4481 4492 @request.session[:user_id] = 2
4482 4493 assert_difference 'Issue.count', 2 do
4483 4494 assert_no_difference 'Project.find(1).issues.count' do
4484 4495 post :bulk_update, :ids => [1, 2], :copy => '1',
4485 4496 :issue => {
4486 4497 :project_id => '2', :tracker_id => '', :assigned_to_id => '2',
4487 4498 :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
4488 4499 }
4489 4500 end
4490 4501 end
4491 4502
4492 4503 copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
4493 4504 assert_equal 2, copied_issues.size
4494 4505 copied_issues.each do |issue|
4495 4506 assert_equal 2, issue.project_id, "Project is incorrect"
4496 4507 assert_equal 2, issue.assigned_to_id, "Assigned to is incorrect"
4497 4508 assert_equal 1, issue.status_id, "Status is incorrect"
4498 4509 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
4499 4510 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
4500 4511 end
4501 4512 end
4502 4513
4503 4514 def test_bulk_copy_should_allow_adding_a_note
4504 4515 @request.session[:user_id] = 2
4505 4516 assert_difference 'Issue.count', 1 do
4506 4517 post :bulk_update, :ids => [1], :copy => '1',
4507 4518 :notes => 'Copying one issue',
4508 4519 :issue => {
4509 4520 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
4510 4521 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
4511 4522 }
4512 4523 end
4513 4524 issue = Issue.order('id DESC').first
4514 4525 assert_equal 1, issue.journals.size
4515 4526 journal = issue.journals.first
4516 4527 assert_equal 'Copying one issue', journal.notes
4517 4528 end
4518 4529
4519 4530 def test_bulk_copy_should_allow_not_copying_the_attachments
4520 4531 attachment_count = Issue.find(3).attachments.size
4521 4532 assert attachment_count > 0
4522 4533 @request.session[:user_id] = 2
4523 4534
4524 4535 assert_difference 'Issue.count', 1 do
4525 4536 assert_no_difference 'Attachment.count' do
4526 4537 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '0',
4527 4538 :issue => {
4528 4539 :project_id => ''
4529 4540 }
4530 4541 end
4531 4542 end
4532 4543 end
4533 4544
4534 4545 def test_bulk_copy_should_allow_copying_the_attachments
4535 4546 attachment_count = Issue.find(3).attachments.size
4536 4547 assert attachment_count > 0
4537 4548 @request.session[:user_id] = 2
4538 4549
4539 4550 assert_difference 'Issue.count', 1 do
4540 4551 assert_difference 'Attachment.count', attachment_count do
4541 4552 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
4542 4553 :issue => {
4543 4554 :project_id => ''
4544 4555 }
4545 4556 end
4546 4557 end
4547 4558 end
4548 4559
4549 4560 def test_bulk_copy_should_add_relations_with_copied_issues
4550 4561 @request.session[:user_id] = 2
4551 4562
4552 4563 assert_difference 'Issue.count', 2 do
4553 4564 assert_difference 'IssueRelation.count', 2 do
4554 4565 post :bulk_update, :ids => [1, 3], :copy => '1', :link_copy => '1',
4555 4566 :issue => {
4556 4567 :project_id => '1'
4557 4568 }
4558 4569 end
4559 4570 end
4560 4571 end
4561 4572
4562 4573 def test_bulk_copy_should_allow_not_copying_the_subtasks
4563 4574 issue = Issue.generate_with_descendants!
4564 4575 @request.session[:user_id] = 2
4565 4576
4566 4577 assert_difference 'Issue.count', 1 do
4567 4578 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '0',
4568 4579 :issue => {
4569 4580 :project_id => ''
4570 4581 }
4571 4582 end
4572 4583 end
4573 4584
4574 4585 def test_bulk_copy_should_allow_copying_the_subtasks
4575 4586 issue = Issue.generate_with_descendants!
4576 4587 count = issue.descendants.count
4577 4588 @request.session[:user_id] = 2
4578 4589
4579 4590 assert_difference 'Issue.count', count+1 do
4580 4591 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
4581 4592 :issue => {
4582 4593 :project_id => ''
4583 4594 }
4584 4595 end
4585 4596 copy = Issue.where(:parent_id => nil).order("id DESC").first
4586 4597 assert_equal count, copy.descendants.count
4587 4598 end
4588 4599
4589 4600 def test_bulk_copy_should_not_copy_selected_subtasks_twice
4590 4601 issue = Issue.generate_with_descendants!
4591 4602 count = issue.descendants.count
4592 4603 @request.session[:user_id] = 2
4593 4604
4594 4605 assert_difference 'Issue.count', count+1 do
4595 4606 post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
4596 4607 :issue => {
4597 4608 :project_id => ''
4598 4609 }
4599 4610 end
4600 4611 copy = Issue.where(:parent_id => nil).order("id DESC").first
4601 4612 assert_equal count, copy.descendants.count
4602 4613 end
4603 4614
4604 4615 def test_bulk_copy_to_another_project_should_follow_when_needed
4605 4616 @request.session[:user_id] = 2
4606 4617 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
4607 4618 issue = Issue.order('id DESC').first
4608 4619 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
4609 4620 end
4610 4621
4611 4622 def test_bulk_copy_with_all_failures_should_display_errors
4612 4623 @request.session[:user_id] = 2
4613 4624 post :bulk_update, :ids => [1, 2], :copy => '1', :issue => {:start_date => 'foo'}
4614 4625
4615 4626 assert_response :success
4616 4627 end
4617 4628
4618 4629 def test_destroy_issue_with_no_time_entries
4619 4630 assert_nil TimeEntry.find_by_issue_id(2)
4620 4631 @request.session[:user_id] = 2
4621 4632
4622 4633 assert_difference 'Issue.count', -1 do
4623 4634 delete :destroy, :id => 2
4624 4635 end
4625 4636 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4626 4637 assert_nil Issue.find_by_id(2)
4627 4638 end
4628 4639
4629 4640 def test_destroy_issues_with_time_entries
4630 4641 @request.session[:user_id] = 2
4631 4642
4632 4643 assert_no_difference 'Issue.count' do
4633 4644 delete :destroy, :ids => [1, 3]
4634 4645 end
4635 4646 assert_response :success
4636 4647 assert_template 'destroy'
4637 4648 assert_not_nil assigns(:hours)
4638 4649 assert Issue.find_by_id(1) && Issue.find_by_id(3)
4639 4650
4640 4651 assert_select 'form' do
4641 4652 assert_select 'input[name=_method][value=delete]'
4642 4653 end
4643 4654 end
4644 4655
4645 4656 def test_destroy_issues_and_destroy_time_entries
4646 4657 @request.session[:user_id] = 2
4647 4658
4648 4659 assert_difference 'Issue.count', -2 do
4649 4660 assert_difference 'TimeEntry.count', -3 do
4650 4661 delete :destroy, :ids => [1, 3], :todo => 'destroy'
4651 4662 end
4652 4663 end
4653 4664 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4654 4665 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4655 4666 assert_nil TimeEntry.find_by_id([1, 2])
4656 4667 end
4657 4668
4658 4669 def test_destroy_issues_and_assign_time_entries_to_project
4659 4670 @request.session[:user_id] = 2
4660 4671
4661 4672 assert_difference 'Issue.count', -2 do
4662 4673 assert_no_difference 'TimeEntry.count' do
4663 4674 delete :destroy, :ids => [1, 3], :todo => 'nullify'
4664 4675 end
4665 4676 end
4666 4677 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4667 4678 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4668 4679 assert_nil TimeEntry.find(1).issue_id
4669 4680 assert_nil TimeEntry.find(2).issue_id
4670 4681 end
4671 4682
4672 4683 def test_destroy_issues_and_reassign_time_entries_to_another_issue
4673 4684 @request.session[:user_id] = 2
4674 4685
4675 4686 assert_difference 'Issue.count', -2 do
4676 4687 assert_no_difference 'TimeEntry.count' do
4677 4688 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
4678 4689 end
4679 4690 end
4680 4691 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4681 4692 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4682 4693 assert_equal 2, TimeEntry.find(1).issue_id
4683 4694 assert_equal 2, TimeEntry.find(2).issue_id
4684 4695 end
4685 4696
4686 4697 def test_destroy_issues_and_reassign_time_entries_to_an_invalid_issue_should_fail
4687 4698 @request.session[:user_id] = 2
4688 4699
4689 4700 assert_no_difference 'Issue.count' do
4690 4701 assert_no_difference 'TimeEntry.count' do
4691 4702 # try to reassign time to an issue of another project
4692 4703 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 4
4693 4704 end
4694 4705 end
4695 4706 assert_response :success
4696 4707 assert_template 'destroy'
4697 4708 end
4698 4709
4699 4710 def test_destroy_issues_from_different_projects
4700 4711 @request.session[:user_id] = 2
4701 4712
4702 4713 assert_difference 'Issue.count', -3 do
4703 4714 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
4704 4715 end
4705 4716 assert_redirected_to :controller => 'issues', :action => 'index'
4706 4717 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
4707 4718 end
4708 4719
4709 4720 def test_destroy_parent_and_child_issues
4710 4721 parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
4711 4722 child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
4712 4723 assert child.is_descendant_of?(parent.reload)
4713 4724
4714 4725 @request.session[:user_id] = 2
4715 4726 assert_difference 'Issue.count', -2 do
4716 4727 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
4717 4728 end
4718 4729 assert_response 302
4719 4730 end
4720 4731
4721 4732 def test_destroy_invalid_should_respond_with_404
4722 4733 @request.session[:user_id] = 2
4723 4734 assert_no_difference 'Issue.count' do
4724 4735 delete :destroy, :id => 999
4725 4736 end
4726 4737 assert_response 404
4727 4738 end
4728 4739
4729 4740 def test_destroy_with_permission_on_tracker_should_be_allowed
4730 4741 role = Role.find(1)
4731 4742 role.set_permission_trackers :delete_issues, [1]
4732 4743 role.save!
4733 4744 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4734 4745
4735 4746 @request.session[:user_id] = 2
4736 4747 assert_difference 'Issue.count', -1 do
4737 4748 delete :destroy, :id => issue.id
4738 4749 end
4739 4750 assert_response 302
4740 4751 end
4741 4752
4742 4753 def test_destroy_without_permission_on_tracker_should_be_denied
4743 4754 role = Role.find(1)
4744 4755 role.set_permission_trackers :delete_issues, [2]
4745 4756 role.save!
4746 4757 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4747 4758
4748 4759 @request.session[:user_id] = 2
4749 4760 assert_no_difference 'Issue.count' do
4750 4761 delete :destroy, :id => issue.id
4751 4762 end
4752 4763 assert_response 403
4753 4764 end
4754 4765
4755 4766 def test_default_search_scope
4756 4767 get :index
4757 4768
4758 4769 assert_select 'div#quick-search form' do
4759 4770 assert_select 'input[name=issues][value="1"][type=hidden]'
4760 4771 end
4761 4772 end
4762 4773
4763 4774 def setup_user_with_copy_but_not_add_permission
4764 4775 Role.all.each {|r| r.remove_permission! :add_issues}
4765 4776 Role.find_by_name('Manager').add_permission! :add_issues
4766 4777 user = User.generate!
4767 4778 User.add_to_project(user, Project.find(1), Role.find_by_name('Developer'))
4768 4779 User.add_to_project(user, Project.find(2), Role.find_by_name('Manager'))
4769 4780 user
4770 4781 end
4771 4782 end
General Comments 0
You need to be logged in to leave comments. Login now