##// END OF EJS Templates
remove trailing white-spaces from test/unit/query_test.rb....
Toshi MARUYAMA -
r6650:fce0c83c0a58
parent child
Show More
@@ -1,764 +1,764
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 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 QueryTest < ActiveSupport::TestCase
21 21 fixtures :projects, :enabled_modules, :users, :members, :member_roles, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :watchers, :custom_fields, :custom_values, :versions, :queries
22 22
23 23 def test_custom_fields_for_all_projects_should_be_available_in_global_queries
24 24 query = Query.new(:project => nil, :name => '_')
25 25 assert query.available_filters.has_key?('cf_1')
26 26 assert !query.available_filters.has_key?('cf_3')
27 27 end
28
28
29 29 def test_system_shared_versions_should_be_available_in_global_queries
30 30 Version.find(2).update_attribute :sharing, 'system'
31 31 query = Query.new(:project => nil, :name => '_')
32 32 assert query.available_filters.has_key?('fixed_version_id')
33 33 assert query.available_filters['fixed_version_id'][:values].detect {|v| v.last == '2'}
34 34 end
35
35
36 36 def test_project_filter_in_global_queries
37 37 query = Query.new(:project => nil, :name => '_')
38 38 project_filter = query.available_filters["project_id"]
39 39 assert_not_nil project_filter
40 40 project_ids = project_filter[:values].map{|p| p[1]}
41 41 assert project_ids.include?("1") #public project
42 42 assert !project_ids.include?("2") #private project user cannot see
43 43 end
44
44
45 45 def find_issues_with_query(query)
46 46 Issue.find :all,
47 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
47 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
48 48 :conditions => query.statement
49 49 end
50 50
51 51 def assert_find_issues_with_query_is_successful(query)
52 52 assert_nothing_raised do
53 53 find_issues_with_query(query)
54 54 end
55 55 end
56 56
57 57 def assert_query_statement_includes(query, condition)
58 58 assert query.statement.include?(condition), "Query statement condition not found in: #{query.statement}"
59 59 end
60 60
61 61 def test_query_should_allow_shared_versions_for_a_project_query
62 62 subproject_version = Version.find(4)
63 63 query = Query.new(:project => Project.find(1), :name => '_')
64 64 query.add_filter('fixed_version_id', '=', [subproject_version.id.to_s])
65 65
66 66 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IN ('4')")
67 67 end
68
68
69 69 def test_query_with_multiple_custom_fields
70 70 query = Query.find(1)
71 71 assert query.valid?
72 72 assert query.statement.include?("#{CustomValue.table_name}.value IN ('MySQL')")
73 73 issues = find_issues_with_query(query)
74 74 assert_equal 1, issues.length
75 75 assert_equal Issue.find(3), issues.first
76 76 end
77
77
78 78 def test_operator_none
79 79 query = Query.new(:project => Project.find(1), :name => '_')
80 80 query.add_filter('fixed_version_id', '!*', [''])
81 81 query.add_filter('cf_1', '!*', [''])
82 82 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL")
83 83 assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''")
84 84 find_issues_with_query(query)
85 85 end
86
86
87 87 def test_operator_none_for_integer
88 88 query = Query.new(:project => Project.find(1), :name => '_')
89 89 query.add_filter('estimated_hours', '!*', [''])
90 90 issues = find_issues_with_query(query)
91 91 assert !issues.empty?
92 92 assert issues.all? {|i| !i.estimated_hours}
93 93 end
94 94
95 95 def test_operator_all
96 96 query = Query.new(:project => Project.find(1), :name => '_')
97 97 query.add_filter('fixed_version_id', '*', [''])
98 98 query.add_filter('cf_1', '*', [''])
99 99 assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL")
100 100 assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''")
101 101 find_issues_with_query(query)
102 102 end
103
103
104 104 def test_numeric_filter_should_not_accept_non_numeric_values
105 105 query = Query.new(:name => '_')
106 106 query.add_filter('estimated_hours', '=', ['a'])
107
107
108 108 assert query.has_filter?('estimated_hours')
109 109 assert !query.valid?
110 110 end
111
111
112 112 def test_operator_is_on_float
113 113 Issue.update_all("estimated_hours = 171.2", "id=2")
114
114
115 115 query = Query.new(:name => '_')
116 116 query.add_filter('estimated_hours', '=', ['171.20'])
117 117 issues = find_issues_with_query(query)
118 118 assert_equal 1, issues.size
119 119 assert_equal 2, issues.first.id
120 120 end
121
121
122 122 def test_operator_greater_than
123 123 query = Query.new(:project => Project.find(1), :name => '_')
124 124 query.add_filter('done_ratio', '>=', ['40'])
125 125 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40.0")
126 126 find_issues_with_query(query)
127 127 end
128
128
129 129 def test_operator_greater_than_a_float
130 130 query = Query.new(:project => Project.find(1), :name => '_')
131 131 query.add_filter('estimated_hours', '>=', ['40.5'])
132 132 assert query.statement.include?("#{Issue.table_name}.estimated_hours >= 40.5")
133 133 find_issues_with_query(query)
134 134 end
135
135
136 136 def test_operator_greater_than_on_custom_field
137 137 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
138 138 query = Query.new(:project => Project.find(1), :name => '_')
139 139 query.add_filter("cf_#{f.id}", '>=', ['40'])
140 140 assert query.statement.include?("CAST(custom_values.value AS decimal(60,3)) >= 40.0")
141 141 find_issues_with_query(query)
142 142 end
143
143
144 144 def test_operator_lesser_than
145 145 query = Query.new(:project => Project.find(1), :name => '_')
146 146 query.add_filter('done_ratio', '<=', ['30'])
147 147 assert query.statement.include?("#{Issue.table_name}.done_ratio <= 30.0")
148 148 find_issues_with_query(query)
149 149 end
150
150
151 151 def test_operator_lesser_than_on_custom_field
152 152 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
153 153 query = Query.new(:project => Project.find(1), :name => '_')
154 154 query.add_filter("cf_#{f.id}", '<=', ['30'])
155 155 assert query.statement.include?("CAST(custom_values.value AS decimal(60,3)) <= 30.0")
156 156 find_issues_with_query(query)
157 157 end
158
158
159 159 def test_operator_between
160 160 query = Query.new(:project => Project.find(1), :name => '_')
161 161 query.add_filter('done_ratio', '><', ['30', '40'])
162 162 assert_include "#{Issue.table_name}.done_ratio BETWEEN 30.0 AND 40.0", query.statement
163 163 find_issues_with_query(query)
164 164 end
165
165
166 166 def test_operator_between_on_custom_field
167 167 f = IssueCustomField.create!(:name => 'filter', :field_format => 'int', :is_filter => true, :is_for_all => true)
168 168 query = Query.new(:project => Project.find(1), :name => '_')
169 169 query.add_filter("cf_#{f.id}", '><', ['30', '40'])
170 170 assert_include "CAST(custom_values.value AS decimal(60,3)) BETWEEN 30.0 AND 40.0", query.statement
171 171 find_issues_with_query(query)
172 172 end
173
173
174 174 def test_date_filter_should_not_accept_non_date_values
175 175 query = Query.new(:name => '_')
176 176 query.add_filter('created_on', '=', ['a'])
177
177
178 178 assert query.has_filter?('created_on')
179 179 assert !query.valid?
180 180 end
181
181
182 182 def test_date_filter_should_not_accept_invalid_date_values
183 183 query = Query.new(:name => '_')
184 184 query.add_filter('created_on', '=', ['2011-01-34'])
185
185
186 186 assert query.has_filter?('created_on')
187 187 assert !query.valid?
188 188 end
189
189
190 190 def test_relative_date_filter_should_not_accept_non_integer_values
191 191 query = Query.new(:name => '_')
192 192 query.add_filter('created_on', '>t-', ['a'])
193
193
194 194 assert query.has_filter?('created_on')
195 195 assert !query.valid?
196 196 end
197 197
198 198 def test_operator_date_equals
199 199 query = Query.new(:name => '_')
200 200 query.add_filter('due_date', '=', ['2011-07-10'])
201 201 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
202 202 find_issues_with_query(query)
203 203 end
204 204
205 205 def test_operator_date_lesser_than
206 206 query = Query.new(:name => '_')
207 207 query.add_filter('due_date', '<=', ['2011-07-10'])
208 208 assert_match /issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
209 209 find_issues_with_query(query)
210 210 end
211 211
212 212 def test_operator_date_greater_than
213 213 query = Query.new(:name => '_')
214 214 query.add_filter('due_date', '>=', ['2011-07-10'])
215 215 assert_match /issues\.due_date > '2011-07-09 23:59:59(\.9+)?'/, query.statement
216 216 find_issues_with_query(query)
217 217 end
218 218
219 219 def test_operator_date_between
220 220 query = Query.new(:name => '_')
221 221 query.add_filter('due_date', '><', ['2011-06-23', '2011-07-10'])
222 222 assert_match /issues\.due_date > '2011-06-22 23:59:59(\.9+)?' AND issues\.due_date <= '2011-07-10 23:59:59(\.9+)?/, query.statement
223 223 find_issues_with_query(query)
224 224 end
225 225
226 226 def test_operator_in_more_than
227 227 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
228 228 query = Query.new(:project => Project.find(1), :name => '_')
229 229 query.add_filter('due_date', '>t+', ['15'])
230 230 issues = find_issues_with_query(query)
231 231 assert !issues.empty?
232 232 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
233 233 end
234 234
235 235 def test_operator_in_less_than
236 236 query = Query.new(:project => Project.find(1), :name => '_')
237 237 query.add_filter('due_date', '<t+', ['15'])
238 238 issues = find_issues_with_query(query)
239 239 assert !issues.empty?
240 240 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
241 241 end
242
242
243 243 def test_operator_less_than_ago
244 244 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
245 245 query = Query.new(:project => Project.find(1), :name => '_')
246 246 query.add_filter('due_date', '>t-', ['3'])
247 247 issues = find_issues_with_query(query)
248 248 assert !issues.empty?
249 249 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
250 250 end
251
251
252 252 def test_operator_more_than_ago
253 253 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
254 254 query = Query.new(:project => Project.find(1), :name => '_')
255 255 query.add_filter('due_date', '<t-', ['10'])
256 256 assert query.statement.include?("#{Issue.table_name}.due_date <=")
257 257 issues = find_issues_with_query(query)
258 258 assert !issues.empty?
259 259 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
260 260 end
261 261
262 262 def test_operator_in
263 263 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
264 264 query = Query.new(:project => Project.find(1), :name => '_')
265 265 query.add_filter('due_date', 't+', ['2'])
266 266 issues = find_issues_with_query(query)
267 267 assert !issues.empty?
268 268 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
269 269 end
270 270
271 271 def test_operator_ago
272 272 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
273 273 query = Query.new(:project => Project.find(1), :name => '_')
274 274 query.add_filter('due_date', 't-', ['3'])
275 275 issues = find_issues_with_query(query)
276 276 assert !issues.empty?
277 277 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
278 278 end
279 279
280 280 def test_operator_today
281 281 query = Query.new(:project => Project.find(1), :name => '_')
282 282 query.add_filter('due_date', 't', [''])
283 283 issues = find_issues_with_query(query)
284 284 assert !issues.empty?
285 285 issues.each {|issue| assert_equal Date.today, issue.due_date}
286 286 end
287 287
288 288 def test_operator_this_week_on_date
289 289 query = Query.new(:project => Project.find(1), :name => '_')
290 290 query.add_filter('due_date', 'w', [''])
291 291 find_issues_with_query(query)
292 292 end
293 293
294 294 def test_operator_this_week_on_datetime
295 295 query = Query.new(:project => Project.find(1), :name => '_')
296 296 query.add_filter('created_on', 'w', [''])
297 297 find_issues_with_query(query)
298 298 end
299 299
300 300 def test_operator_contains
301 301 query = Query.new(:project => Project.find(1), :name => '_')
302 302 query.add_filter('subject', '~', ['uNable'])
303 303 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'")
304 304 result = find_issues_with_query(query)
305 305 assert result.empty?
306 306 result.each {|issue| assert issue.subject.downcase.include?('unable') }
307 307 end
308
308
309 309 def test_range_for_this_week_with_week_starting_on_monday
310 310 I18n.locale = :fr
311 311 assert_equal '1', I18n.t(:general_first_day_of_week)
312
312
313 313 Date.stubs(:today).returns(Date.parse('2011-04-29'))
314
314
315 315 query = Query.new(:project => Project.find(1), :name => '_')
316 316 query.add_filter('due_date', 'w', [''])
317 317 assert query.statement.match(/issues\.due_date > '2011-04-24 23:59:59(\.9+)?' AND issues\.due_date <= '2011-05-01 23:59:59(\.9+)?/), "range not found in #{query.statement}"
318 318 I18n.locale = :en
319 319 end
320
320
321 321 def test_range_for_this_week_with_week_starting_on_sunday
322 322 I18n.locale = :en
323 323 assert_equal '7', I18n.t(:general_first_day_of_week)
324
324
325 325 Date.stubs(:today).returns(Date.parse('2011-04-29'))
326
326
327 327 query = Query.new(:project => Project.find(1), :name => '_')
328 328 query.add_filter('due_date', 'w', [''])
329 329 assert query.statement.match(/issues\.due_date > '2011-04-23 23:59:59(\.9+)?' AND issues\.due_date <= '2011-04-30 23:59:59(\.9+)?/), "range not found in #{query.statement}"
330 330 end
331
331
332 332 def test_operator_does_not_contains
333 333 query = Query.new(:project => Project.find(1), :name => '_')
334 334 query.add_filter('subject', '!~', ['uNable'])
335 335 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'")
336 336 find_issues_with_query(query)
337 337 end
338
338
339 339 def test_filter_assigned_to_me
340 340 user = User.find(2)
341 341 group = Group.find(10)
342 342 User.current = user
343 343 i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
344 344 i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
345 345 i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => Group.find(11))
346 346 group.users << user
347
347
348 348 query = Query.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
349 349 result = query.issues
350 350 assert_equal Issue.visible.all(:conditions => {:assigned_to_id => ([2] + user.reload.group_ids)}).sort_by(&:id), result.sort_by(&:id)
351
351
352 352 assert result.include?(i1)
353 353 assert result.include?(i2)
354 354 assert !result.include?(i3)
355 355 end
356
356
357 357 def test_filter_watched_issues
358 358 User.current = User.find(1)
359 359 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
360 360 result = find_issues_with_query(query)
361 361 assert_not_nil result
362 362 assert !result.empty?
363 363 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
364 364 User.current = nil
365 365 end
366
366
367 367 def test_filter_unwatched_issues
368 368 User.current = User.find(1)
369 369 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
370 370 result = find_issues_with_query(query)
371 371 assert_not_nil result
372 372 assert !result.empty?
373 373 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
374 374 User.current = nil
375 375 end
376
376
377 377 def test_statement_should_be_nil_with_no_filters
378 378 q = Query.new(:name => '_')
379 379 q.filters = {}
380
380
381 381 assert q.valid?
382 382 assert_nil q.statement
383 383 end
384
384
385 385 def test_default_columns
386 386 q = Query.new
387 assert !q.columns.empty?
387 assert !q.columns.empty?
388 388 end
389
389
390 390 def test_set_column_names
391 391 q = Query.new
392 392 q.column_names = ['tracker', :subject, '', 'unknonw_column']
393 393 assert_equal [:tracker, :subject], q.columns.collect {|c| c.name}
394 394 c = q.columns.first
395 395 assert q.has_column?(c)
396 396 end
397
397
398 398 def test_groupable_columns_should_include_custom_fields
399 399 q = Query.new
400 400 assert q.groupable_columns.detect {|c| c.is_a? QueryCustomFieldColumn}
401 401 end
402 402
403 403 def test_grouped_with_valid_column
404 404 q = Query.new(:group_by => 'status')
405 405 assert q.grouped?
406 406 assert_not_nil q.group_by_column
407 407 assert_equal :status, q.group_by_column.name
408 408 assert_not_nil q.group_by_statement
409 409 assert_equal 'status', q.group_by_statement
410 410 end
411
411
412 412 def test_grouped_with_invalid_column
413 413 q = Query.new(:group_by => 'foo')
414 414 assert !q.grouped?
415 415 assert_nil q.group_by_column
416 416 assert_nil q.group_by_statement
417 417 end
418
418
419 419 def test_default_sort
420 420 q = Query.new
421 421 assert_equal [], q.sort_criteria
422 422 end
423
423
424 424 def test_set_sort_criteria_with_hash
425 425 q = Query.new
426 426 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
427 427 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
428 428 end
429
429
430 430 def test_set_sort_criteria_with_array
431 431 q = Query.new
432 432 q.sort_criteria = [['priority', 'desc'], 'tracker']
433 433 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
434 434 end
435
435
436 436 def test_create_query_with_sort
437 437 q = Query.new(:name => 'Sorted')
438 438 q.sort_criteria = [['priority', 'desc'], 'tracker']
439 439 assert q.save
440 440 q.reload
441 441 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
442 442 end
443
443
444 444 def test_sort_by_string_custom_field_asc
445 445 q = Query.new
446 446 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
447 447 assert c
448 448 assert c.sortable
449 449 issues = Issue.find :all,
450 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
450 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
451 451 :conditions => q.statement,
452 452 :order => "#{c.sortable} ASC"
453 453 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
454 454 assert !values.empty?
455 455 assert_equal values.sort, values
456 456 end
457
457
458 458 def test_sort_by_string_custom_field_desc
459 459 q = Query.new
460 460 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
461 461 assert c
462 462 assert c.sortable
463 463 issues = Issue.find :all,
464 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
464 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
465 465 :conditions => q.statement,
466 466 :order => "#{c.sortable} DESC"
467 467 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
468 468 assert !values.empty?
469 469 assert_equal values.sort.reverse, values
470 470 end
471
471
472 472 def test_sort_by_float_custom_field_asc
473 473 q = Query.new
474 474 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
475 475 assert c
476 476 assert c.sortable
477 477 issues = Issue.find :all,
478 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
478 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
479 479 :conditions => q.statement,
480 480 :order => "#{c.sortable} ASC"
481 481 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
482 482 assert !values.empty?
483 483 assert_equal values.sort, values
484 484 end
485
485
486 486 def test_invalid_query_should_raise_query_statement_invalid_error
487 487 q = Query.new
488 488 assert_raise Query::StatementInvalid do
489 489 q.issues(:conditions => "foo = 1")
490 490 end
491 491 end
492 492
493 493 def test_issue_count
494 494 q = Query.new(:name => '_')
495 495 issue_count = q.issue_count
496 496 assert_equal q.issues.size, issue_count
497 497 end
498 498
499 499 def test_issue_count_with_archived_issues
500 500 p = Project.generate!( :status => Project::STATUS_ARCHIVED )
501 501 i = Issue.generate!( :project => p, :tracker => p.trackers.first )
502 502 assert !i.visible?
503 503
504 504 test_issue_count
505 505 end
506 506
507 507 def test_issue_count_by_association_group
508 508 q = Query.new(:name => '_', :group_by => 'assigned_to')
509 509 count_by_group = q.issue_count_by_group
510 510 assert_kind_of Hash, count_by_group
511 511 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
512 512 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
513 513 assert count_by_group.has_key?(User.find(3))
514 514 end
515 515
516 516 def test_issue_count_by_list_custom_field_group
517 517 q = Query.new(:name => '_', :group_by => 'cf_1')
518 518 count_by_group = q.issue_count_by_group
519 519 assert_kind_of Hash, count_by_group
520 520 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
521 521 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
522 522 assert count_by_group.has_key?('MySQL')
523 523 end
524
524
525 525 def test_issue_count_by_date_custom_field_group
526 526 q = Query.new(:name => '_', :group_by => 'cf_8')
527 527 count_by_group = q.issue_count_by_group
528 528 assert_kind_of Hash, count_by_group
529 529 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
530 530 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
531 531 end
532
532
533 533 def test_label_for
534 534 q = Query.new
535 535 assert_equal 'assigned_to', q.label_for('assigned_to_id')
536 536 end
537
537
538 538 def test_editable_by
539 539 admin = User.find(1)
540 540 manager = User.find(2)
541 541 developer = User.find(3)
542
542
543 543 # Public query on project 1
544 544 q = Query.find(1)
545 545 assert q.editable_by?(admin)
546 546 assert q.editable_by?(manager)
547 547 assert !q.editable_by?(developer)
548 548
549 549 # Private query on project 1
550 550 q = Query.find(2)
551 551 assert q.editable_by?(admin)
552 552 assert !q.editable_by?(manager)
553 553 assert q.editable_by?(developer)
554 554
555 555 # Private query for all projects
556 556 q = Query.find(3)
557 557 assert q.editable_by?(admin)
558 558 assert !q.editable_by?(manager)
559 559 assert q.editable_by?(developer)
560 560
561 561 # Public query for all projects
562 562 q = Query.find(4)
563 563 assert q.editable_by?(admin)
564 564 assert !q.editable_by?(manager)
565 565 assert !q.editable_by?(developer)
566 566 end
567
567
568 568 def test_visible_scope
569 569 query_ids = Query.visible(User.anonymous).map(&:id)
570
570
571 571 assert query_ids.include?(1), 'public query on public project was not visible'
572 572 assert query_ids.include?(4), 'public query for all projects was not visible'
573 573 assert !query_ids.include?(2), 'private query on public project was visible'
574 574 assert !query_ids.include?(3), 'private query for all projects was visible'
575 575 assert !query_ids.include?(7), 'public query on private project was visible'
576 576 end
577 577
578 578 context "#available_filters" do
579 579 setup do
580 580 @query = Query.new(:name => "_")
581 581 end
582
582
583 583 should "include users of visible projects in cross-project view" do
584 584 users = @query.available_filters["assigned_to_id"]
585 585 assert_not_nil users
586 586 assert users[:values].map{|u|u[1]}.include?("3")
587 587 end
588 588
589 589 should "include visible projects in cross-project view" do
590 590 projects = @query.available_filters["project_id"]
591 591 assert_not_nil projects
592 592 assert projects[:values].map{|u|u[1]}.include?("1")
593 593 end
594 594
595 595 context "'member_of_group' filter" do
596 596 should "be present" do
597 597 assert @query.available_filters.keys.include?("member_of_group")
598 598 end
599
599
600 600 should "be an optional list" do
601 601 assert_equal :list_optional, @query.available_filters["member_of_group"][:type]
602 602 end
603
603
604 604 should "have a list of the groups as values" do
605 605 Group.destroy_all # No fixtures
606 606 group1 = Group.generate!.reload
607 607 group2 = Group.generate!.reload
608 608
609 609 expected_group_list = [
610 610 [group1.name, group1.id.to_s],
611 611 [group2.name, group2.id.to_s]
612 612 ]
613 613 assert_equal expected_group_list.sort, @query.available_filters["member_of_group"][:values].sort
614 614 end
615 615
616 616 end
617 617
618 618 context "'assigned_to_role' filter" do
619 619 should "be present" do
620 620 assert @query.available_filters.keys.include?("assigned_to_role")
621 621 end
622
622
623 623 should "be an optional list" do
624 624 assert_equal :list_optional, @query.available_filters["assigned_to_role"][:type]
625 625 end
626
626
627 627 should "have a list of the Roles as values" do
628 628 assert @query.available_filters["assigned_to_role"][:values].include?(['Manager','1'])
629 629 assert @query.available_filters["assigned_to_role"][:values].include?(['Developer','2'])
630 630 assert @query.available_filters["assigned_to_role"][:values].include?(['Reporter','3'])
631 631 end
632 632
633 633 should "not include the built in Roles as values" do
634 634 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Non member','4'])
635 635 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Anonymous','5'])
636 636 end
637 637
638 638 end
639 639
640 640 end
641 641
642 642 context "#statement" do
643 643 context "with 'member_of_group' filter" do
644 644 setup do
645 645 Group.destroy_all # No fixtures
646 646 @user_in_group = User.generate!
647 647 @second_user_in_group = User.generate!
648 648 @user_in_group2 = User.generate!
649 649 @user_not_in_group = User.generate!
650
650
651 651 @group = Group.generate!.reload
652 652 @group.users << @user_in_group
653 653 @group.users << @second_user_in_group
654
654
655 655 @group2 = Group.generate!.reload
656 656 @group2.users << @user_in_group2
657
657
658 658 end
659
659
660 660 should "search assigned to for users in the group" do
661 661 @query = Query.new(:name => '_')
662 662 @query.add_filter('member_of_group', '=', [@group.id.to_s])
663 663
664 664 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}')"
665 665 assert_find_issues_with_query_is_successful @query
666 666 end
667 667
668 668 should "search not assigned to any group member (none)" do
669 669 @query = Query.new(:name => '_')
670 670 @query.add_filter('member_of_group', '!*', [''])
671 671
672 672 # Users not in a group
673 673 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IS NULL OR #{Issue.table_name}.assigned_to_id NOT IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}')"
674 674 assert_find_issues_with_query_is_successful @query
675 675 end
676 676
677 677 should "search assigned to any group member (all)" do
678 678 @query = Query.new(:name => '_')
679 679 @query.add_filter('member_of_group', '*', [''])
680 680
681 681 # Only users in a group
682 682 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}','#{@user_in_group2.id}')"
683 683 assert_find_issues_with_query_is_successful @query
684 684 end
685
685
686 686 should "return an empty set with = empty group" do
687 687 @empty_group = Group.generate!
688 688 @query = Query.new(:name => '_')
689 689 @query.add_filter('member_of_group', '=', [@empty_group.id.to_s])
690
690
691 691 assert_equal [], find_issues_with_query(@query)
692 692 end
693
693
694 694 should "return issues with ! empty group" do
695 695 @empty_group = Group.generate!
696 696 @query = Query.new(:name => '_')
697 697 @query.add_filter('member_of_group', '!', [@empty_group.id.to_s])
698
698
699 699 assert_find_issues_with_query_is_successful @query
700 700 end
701 701 end
702 702
703 703 context "with 'assigned_to_role' filter" do
704 704 setup do
705 705 # No fixtures
706 706 MemberRole.delete_all
707 707 Member.delete_all
708 708 Role.delete_all
709
709
710 710 @manager_role = Role.generate!(:name => 'Manager')
711 711 @developer_role = Role.generate!(:name => 'Developer')
712 712
713 713 @project = Project.generate!
714 714 @manager = User.generate!
715 715 @developer = User.generate!
716 716 @boss = User.generate!
717 717 User.add_to_project(@manager, @project, @manager_role)
718 718 User.add_to_project(@developer, @project, @developer_role)
719 719 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
720 720 end
721
721
722 722 should "search assigned to for users with the Role" do
723 723 @query = Query.new(:name => '_')
724 724 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
725 725
726 726 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@manager.id}','#{@boss.id}')"
727 727 assert_find_issues_with_query_is_successful @query
728 728 end
729 729
730 730 should "search assigned to for users not assigned to any Role (none)" do
731 731 @query = Query.new(:name => '_')
732 732 @query.add_filter('assigned_to_role', '!*', [''])
733 733
734 734 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IS NULL OR #{Issue.table_name}.assigned_to_id NOT IN ('#{@manager.id}','#{@developer.id}','#{@boss.id}')"
735 735 assert_find_issues_with_query_is_successful @query
736 736 end
737 737
738 738 should "search assigned to for users assigned to any Role (all)" do
739 739 @query = Query.new(:name => '_')
740 740 @query.add_filter('assigned_to_role', '*', [''])
741 741
742 742 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@manager.id}','#{@developer.id}','#{@boss.id}')"
743 743 assert_find_issues_with_query_is_successful @query
744 744 end
745
745
746 746 should "return an empty set with empty role" do
747 747 @empty_role = Role.generate!
748 748 @query = Query.new(:name => '_')
749 749 @query.add_filter('assigned_to_role', '=', [@empty_role.id.to_s])
750
750
751 751 assert_equal [], find_issues_with_query(@query)
752 752 end
753
753
754 754 should "return issues with ! empty role" do
755 755 @empty_role = Role.generate!
756 756 @query = Query.new(:name => '_')
757 757 @query.add_filter('member_of_group', '!', [@empty_role.id.to_s])
758
758
759 759 assert_find_issues_with_query_is_successful @query
760 760 end
761 761 end
762 762 end
763
763
764 764 end
General Comments 0
You need to be logged in to leave comments. Login now