##// END OF EJS Templates
Merged r14472 (#20427)....
Jean-Philippe Lang -
r14164:2a15166f9be9
parent child
Show More
@@ -1,128 +1,129
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 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 class QueriesController < ApplicationController
19 19 menu_item :issues
20 20 before_filter :find_query, :except => [:new, :create, :index]
21 21 before_filter :find_optional_project, :only => [:new, :create]
22 22
23 23 accept_api_auth :index
24 24
25 25 include QueriesHelper
26 26
27 27 def index
28 28 case params[:format]
29 29 when 'xml', 'json'
30 30 @offset, @limit = api_offset_and_limit
31 31 else
32 32 @limit = per_page_option
33 33 end
34 34 @query_count = IssueQuery.visible.count
35 35 @query_pages = Paginator.new @query_count, @limit, params['page']
36 36 @queries = IssueQuery.visible.
37 37 order("#{Query.table_name}.name").
38 38 limit(@limit).
39 39 offset(@offset).
40 40 to_a
41 41 respond_to do |format|
42 42 format.html {render_error :status => 406}
43 43 format.api
44 44 end
45 45 end
46 46
47 47 def new
48 48 @query = IssueQuery.new
49 49 @query.user = User.current
50 50 @query.project = @project
51 51 @query.build_from_params(params)
52 52 end
53 53
54 54 def create
55 55 @query = IssueQuery.new
56 56 @query.user = User.current
57 57 @query.project = @project
58 58 update_query_from_params
59 59
60 60 if @query.save
61 61 flash[:notice] = l(:notice_successful_create)
62 62 redirect_to_issues(:query_id => @query)
63 63 else
64 64 render :action => 'new', :layout => !request.xhr?
65 65 end
66 66 end
67 67
68 68 def edit
69 69 end
70 70
71 71 def update
72 72 update_query_from_params
73 73
74 74 if @query.save
75 75 flash[:notice] = l(:notice_successful_update)
76 76 redirect_to_issues(:query_id => @query)
77 77 else
78 78 render :action => 'edit'
79 79 end
80 80 end
81 81
82 82 def destroy
83 83 @query.destroy
84 84 redirect_to_issues(:set_filter => 1)
85 85 end
86 86
87 87 private
88 88 def find_query
89 89 @query = IssueQuery.find(params[:id])
90 90 @project = @query.project
91 91 render_403 unless @query.editable_by?(User.current)
92 92 rescue ActiveRecord::RecordNotFound
93 93 render_404
94 94 end
95 95
96 96 def find_optional_project
97 97 @project = Project.find(params[:project_id]) if params[:project_id]
98 98 render_403 unless User.current.allowed_to?(:save_queries, @project, :global => true)
99 99 rescue ActiveRecord::RecordNotFound
100 100 render_404
101 101 end
102 102
103 103 def update_query_from_params
104 104 @query.project = params[:query_is_for_all] ? nil : @project
105 105 @query.build_from_params(params)
106 106 @query.column_names = nil if params[:default_columns]
107 107 @query.sort_criteria = params[:query] && params[:query][:sort_criteria]
108 108 @query.name = params[:query] && params[:query][:name]
109 109 if User.current.allowed_to?(:manage_public_queries, @query.project) || User.current.admin?
110 110 @query.visibility = (params[:query] && params[:query][:visibility]) || IssueQuery::VISIBILITY_PRIVATE
111 @query.role_ids = params[:query] && params[:query][:role_ids]
111 112 else
112 113 @query.visibility = IssueQuery::VISIBILITY_PRIVATE
113 114 end
114 115 @query
115 116 end
116 117
117 118 def redirect_to_issues(options)
118 119 if params[:gantt]
119 120 if @project
120 121 redirect_to project_gantt_path(@project, options)
121 122 else
122 123 redirect_to issues_gantt_path(options)
123 124 end
124 125 else
125 126 redirect_to _project_issues_path(@project, options)
126 127 end
127 128 end
128 129 end
@@ -1,358 +1,374
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 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 QueriesControllerTest < ActionController::TestCase
21 21 fixtures :projects, :users, :members, :member_roles, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries, :enabled_modules
22 22
23 23 def setup
24 24 User.current = nil
25 25 end
26 26
27 27 def test_index
28 28 get :index
29 29 # HTML response not implemented
30 30 assert_response 406
31 31 end
32 32
33 33 def test_new_project_query
34 34 @request.session[:user_id] = 2
35 35 get :new, :project_id => 1
36 36 assert_response :success
37 37 assert_template 'new'
38 38 assert_select 'input[name=?][value="0"][checked=checked]', 'query[visibility]'
39 39 assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked]):not([disabled])'
40 40 assert_select 'select[name=?]', 'c[]' do
41 41 assert_select 'option[value=tracker]'
42 42 assert_select 'option[value=subject]'
43 43 end
44 44 end
45 45
46 46 def test_new_global_query
47 47 @request.session[:user_id] = 2
48 48 get :new
49 49 assert_response :success
50 50 assert_template 'new'
51 51 assert_select 'input[name=?]', 'query[visibility]', 0
52 52 assert_select 'input[name=query_is_for_all][type=checkbox][checked]:not([disabled])'
53 53 end
54 54
55 55 def test_new_on_invalid_project
56 56 @request.session[:user_id] = 2
57 57 get :new, :project_id => 'invalid'
58 58 assert_response 404
59 59 end
60 60
61 61 def test_create_project_public_query
62 62 @request.session[:user_id] = 2
63 63 post :create,
64 64 :project_id => 'ecookbook',
65 65 :default_columns => '1',
66 66 :f => ["status_id", "assigned_to_id"],
67 67 :op => {"assigned_to_id" => "=", "status_id" => "o"},
68 68 :v => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
69 69 :query => {"name" => "test_new_project_public_query", "visibility" => "2"}
70 70
71 71 q = Query.find_by_name('test_new_project_public_query')
72 72 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
73 73 assert q.is_public?
74 74 assert q.has_default_columns?
75 75 assert q.valid?
76 76 end
77 77
78 78 def test_create_project_private_query
79 79 @request.session[:user_id] = 3
80 80 post :create,
81 81 :project_id => 'ecookbook',
82 82 :default_columns => '1',
83 83 :fields => ["status_id", "assigned_to_id"],
84 84 :operators => {"assigned_to_id" => "=", "status_id" => "o"},
85 85 :values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
86 86 :query => {"name" => "test_new_project_private_query", "visibility" => "0"}
87 87
88 88 q = Query.find_by_name('test_new_project_private_query')
89 89 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
90 90 assert !q.is_public?
91 91 assert q.has_default_columns?
92 92 assert q.valid?
93 93 end
94 94
95 def test_create_project_roles_query
96 @request.session[:user_id] = 2
97 post :create,
98 :project_id => 'ecookbook',
99 :default_columns => '1',
100 :fields => ["status_id", "assigned_to_id"],
101 :operators => {"assigned_to_id" => "=", "status_id" => "o"},
102 :values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
103 :query => {"name" => "test_create_project_roles_query", "visibility" => "1", "role_ids" => ["1", "2", ""]}
104
105 q = Query.find_by_name('test_create_project_roles_query')
106 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
107 assert_equal Query::VISIBILITY_ROLES, q.visibility
108 assert_equal [1, 2], q.roles.ids.sort
109 end
110
95 111 def test_create_global_private_query_with_custom_columns
96 112 @request.session[:user_id] = 3
97 113 post :create,
98 114 :fields => ["status_id", "assigned_to_id"],
99 115 :operators => {"assigned_to_id" => "=", "status_id" => "o"},
100 116 :values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
101 117 :query => {"name" => "test_new_global_private_query", "visibility" => "0"},
102 118 :c => ["", "tracker", "subject", "priority", "category"]
103 119
104 120 q = Query.find_by_name('test_new_global_private_query')
105 121 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
106 122 assert !q.is_public?
107 123 assert !q.has_default_columns?
108 124 assert_equal [:id, :tracker, :subject, :priority, :category], q.columns.collect {|c| c.name}
109 125 assert q.valid?
110 126 end
111 127
112 128 def test_create_global_query_with_custom_filters
113 129 @request.session[:user_id] = 3
114 130 post :create,
115 131 :fields => ["assigned_to_id"],
116 132 :operators => {"assigned_to_id" => "="},
117 133 :values => { "assigned_to_id" => ["me"]},
118 134 :query => {"name" => "test_new_global_query"}
119 135
120 136 q = Query.find_by_name('test_new_global_query')
121 137 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
122 138 assert !q.is_public?
123 139 assert !q.has_filter?(:status_id)
124 140 assert_equal ['assigned_to_id'], q.filters.keys
125 141 assert q.valid?
126 142 end
127 143
128 144 def test_create_with_sort
129 145 @request.session[:user_id] = 1
130 146 post :create,
131 147 :default_columns => '1',
132 148 :operators => {"status_id" => "o"},
133 149 :values => {"status_id" => ["1"]},
134 150 :query => {:name => "test_new_with_sort",
135 151 :visibility => "2",
136 152 :sort_criteria => {"0" => ["due_date", "desc"], "1" => ["tracker", ""]}}
137 153
138 154 query = Query.find_by_name("test_new_with_sort")
139 155 assert_not_nil query
140 156 assert_equal [['due_date', 'desc'], ['tracker', 'asc']], query.sort_criteria
141 157 end
142 158
143 159 def test_create_with_failure
144 160 @request.session[:user_id] = 2
145 161 assert_no_difference '::Query.count' do
146 162 post :create, :project_id => 'ecookbook', :query => {:name => ''}
147 163 end
148 164 assert_response :success
149 165 assert_template 'new'
150 166 assert_select 'input[name=?]', 'query[name]'
151 167 end
152 168
153 169 def test_create_global_query_from_gantt
154 170 @request.session[:user_id] = 1
155 171 assert_difference 'IssueQuery.count' do
156 172 post :create,
157 173 :gantt => 1,
158 174 :operators => {"status_id" => "o"},
159 175 :values => {"status_id" => ["1"]},
160 176 :query => {:name => "test_create_from_gantt",
161 177 :draw_relations => '1',
162 178 :draw_progress_line => '1'}
163 179 assert_response 302
164 180 end
165 181 query = IssueQuery.order('id DESC').first
166 182 assert_redirected_to "/issues/gantt?query_id=#{query.id}"
167 183 assert_equal true, query.draw_relations
168 184 assert_equal true, query.draw_progress_line
169 185 end
170 186
171 187 def test_create_project_query_from_gantt
172 188 @request.session[:user_id] = 1
173 189 assert_difference 'IssueQuery.count' do
174 190 post :create,
175 191 :project_id => 'ecookbook',
176 192 :gantt => 1,
177 193 :operators => {"status_id" => "o"},
178 194 :values => {"status_id" => ["1"]},
179 195 :query => {:name => "test_create_from_gantt",
180 196 :draw_relations => '0',
181 197 :draw_progress_line => '0'}
182 198 assert_response 302
183 199 end
184 200 query = IssueQuery.order('id DESC').first
185 201 assert_redirected_to "/projects/ecookbook/issues/gantt?query_id=#{query.id}"
186 202 assert_equal false, query.draw_relations
187 203 assert_equal false, query.draw_progress_line
188 204 end
189 205
190 206 def test_create_project_public_query_should_force_private_without_manage_public_queries_permission
191 207 @request.session[:user_id] = 3
192 208 query = new_record(Query) do
193 209 post :create,
194 210 :project_id => 'ecookbook',
195 211 :query => {"name" => "name", "visibility" => "2"}
196 212 assert_response 302
197 213 end
198 214 assert_not_nil query.project
199 215 assert_equal Query::VISIBILITY_PRIVATE, query.visibility
200 216 end
201 217
202 218 def test_create_global_public_query_should_force_private_without_manage_public_queries_permission
203 219 @request.session[:user_id] = 3
204 220 query = new_record(Query) do
205 221 post :create,
206 222 :project_id => 'ecookbook', :query_is_for_all => '1',
207 223 :query => {"name" => "name", "visibility" => "2"}
208 224 assert_response 302
209 225 end
210 226 assert_nil query.project
211 227 assert_equal Query::VISIBILITY_PRIVATE, query.visibility
212 228 end
213 229
214 230 def test_create_project_public_query_with_manage_public_queries_permission
215 231 @request.session[:user_id] = 2
216 232 query = new_record(Query) do
217 233 post :create,
218 234 :project_id => 'ecookbook',
219 235 :query => {"name" => "name", "visibility" => "2"}
220 236 assert_response 302
221 237 end
222 238 assert_not_nil query.project
223 239 assert_equal Query::VISIBILITY_PUBLIC, query.visibility
224 240 end
225 241
226 242 def test_create_global_public_query_should_force_private_with_manage_public_queries_permission
227 243 @request.session[:user_id] = 2
228 244 query = new_record(Query) do
229 245 post :create,
230 246 :project_id => 'ecookbook', :query_is_for_all => '1',
231 247 :query => {"name" => "name", "visibility" => "2"}
232 248 assert_response 302
233 249 end
234 250 assert_nil query.project
235 251 assert_equal Query::VISIBILITY_PRIVATE, query.visibility
236 252 end
237 253
238 254 def test_create_global_public_query_by_admin
239 255 @request.session[:user_id] = 1
240 256 query = new_record(Query) do
241 257 post :create,
242 258 :project_id => 'ecookbook', :query_is_for_all => '1',
243 259 :query => {"name" => "name", "visibility" => "2"}
244 260 assert_response 302
245 261 end
246 262 assert_nil query.project
247 263 assert_equal Query::VISIBILITY_PUBLIC, query.visibility
248 264 end
249 265
250 266 def test_edit_global_public_query
251 267 @request.session[:user_id] = 1
252 268 get :edit, :id => 4
253 269 assert_response :success
254 270 assert_template 'edit'
255 271 assert_select 'input[name=?][value="2"][checked=checked]', 'query[visibility]'
256 272 assert_select 'input[name=query_is_for_all][type=checkbox][checked=checked]'
257 273 end
258 274
259 275 def test_edit_global_private_query
260 276 @request.session[:user_id] = 3
261 277 get :edit, :id => 3
262 278 assert_response :success
263 279 assert_template 'edit'
264 280 assert_select 'input[name=?]', 'query[visibility]', 0
265 281 assert_select 'input[name=query_is_for_all][type=checkbox][checked=checked]'
266 282 end
267 283
268 284 def test_edit_project_private_query
269 285 @request.session[:user_id] = 3
270 286 get :edit, :id => 2
271 287 assert_response :success
272 288 assert_template 'edit'
273 289 assert_select 'input[name=?]', 'query[visibility]', 0
274 290 assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked])'
275 291 end
276 292
277 293 def test_edit_project_public_query
278 294 @request.session[:user_id] = 2
279 295 get :edit, :id => 1
280 296 assert_response :success
281 297 assert_template 'edit'
282 298 assert_select 'input[name=?][value="2"][checked=checked]', 'query[visibility]'
283 299 assert_select 'input[name=query_is_for_all][type=checkbox]:not([checked])'
284 300 end
285 301
286 302 def test_edit_sort_criteria
287 303 @request.session[:user_id] = 1
288 304 get :edit, :id => 5
289 305 assert_response :success
290 306 assert_template 'edit'
291 307 assert_select 'select[name=?]', 'query[sort_criteria][0][]' do
292 308 assert_select 'option[value=priority][selected=selected]'
293 309 assert_select 'option[value=desc][selected=selected]'
294 310 end
295 311 end
296 312
297 313 def test_edit_invalid_query
298 314 @request.session[:user_id] = 2
299 315 get :edit, :id => 99
300 316 assert_response 404
301 317 end
302 318
303 319 def test_udpate_global_private_query
304 320 @request.session[:user_id] = 3
305 321 put :update,
306 322 :id => 3,
307 323 :default_columns => '1',
308 324 :fields => ["status_id", "assigned_to_id"],
309 325 :operators => {"assigned_to_id" => "=", "status_id" => "o"},
310 326 :values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
311 327 :query => {"name" => "test_edit_global_private_query", "visibility" => "2"}
312 328
313 329 assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 3
314 330 q = Query.find_by_name('test_edit_global_private_query')
315 331 assert !q.is_public?
316 332 assert q.has_default_columns?
317 333 assert q.valid?
318 334 end
319 335
320 336 def test_update_global_public_query
321 337 @request.session[:user_id] = 1
322 338 put :update,
323 339 :id => 4,
324 340 :default_columns => '1',
325 341 :fields => ["status_id", "assigned_to_id"],
326 342 :operators => {"assigned_to_id" => "=", "status_id" => "o"},
327 343 :values => { "assigned_to_id" => ["1"], "status_id" => ["1"]},
328 344 :query => {"name" => "test_edit_global_public_query", "visibility" => "2"}
329 345
330 346 assert_redirected_to :controller => 'issues', :action => 'index', :query_id => 4
331 347 q = Query.find_by_name('test_edit_global_public_query')
332 348 assert q.is_public?
333 349 assert q.has_default_columns?
334 350 assert q.valid?
335 351 end
336 352
337 353 def test_update_with_failure
338 354 @request.session[:user_id] = 1
339 355 put :update, :id => 4, :query => {:name => ''}
340 356 assert_response :success
341 357 assert_template 'edit'
342 358 end
343 359
344 360 def test_destroy
345 361 @request.session[:user_id] = 2
346 362 delete :destroy, :id => 1
347 363 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :set_filter => 1, :query_id => nil
348 364 assert_nil Query.find_by_id(1)
349 365 end
350 366
351 367 def test_backslash_should_be_escaped_in_filters
352 368 @request.session[:user_id] = 2
353 369 get :new, :subject => 'foo/bar'
354 370 assert_response :success
355 371 assert_template 'new'
356 372 assert_include 'addFilter("subject", "=", ["foo\/bar"]);', response.body
357 373 end
358 374 end
General Comments 0
You need to be logged in to leave comments. Login now