##// END OF EJS Templates
Fix failing test....
Eric Davis -
r3992:e58513c9767a
parent child
Show More
@@ -1,524 +1,524
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2008 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.dirname(__FILE__) + '/../test_helper'
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 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_operator_greater_than
105 105 query = Query.new(:project => Project.find(1), :name => '_')
106 106 query.add_filter('done_ratio', '>=', ['40'])
107 107 assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40")
108 108 find_issues_with_query(query)
109 109 end
110 110
111 111 def test_operator_in_more_than
112 112 Issue.find(7).update_attribute(:due_date, (Date.today + 15))
113 113 query = Query.new(:project => Project.find(1), :name => '_')
114 114 query.add_filter('due_date', '>t+', ['15'])
115 115 issues = find_issues_with_query(query)
116 116 assert !issues.empty?
117 117 issues.each {|issue| assert(issue.due_date >= (Date.today + 15))}
118 118 end
119 119
120 120 def test_operator_in_less_than
121 121 query = Query.new(:project => Project.find(1), :name => '_')
122 122 query.add_filter('due_date', '<t+', ['15'])
123 123 issues = find_issues_with_query(query)
124 124 assert !issues.empty?
125 125 issues.each {|issue| assert(issue.due_date >= Date.today && issue.due_date <= (Date.today + 15))}
126 126 end
127 127
128 128 def test_operator_less_than_ago
129 129 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
130 130 query = Query.new(:project => Project.find(1), :name => '_')
131 131 query.add_filter('due_date', '>t-', ['3'])
132 132 issues = find_issues_with_query(query)
133 133 assert !issues.empty?
134 134 issues.each {|issue| assert(issue.due_date >= (Date.today - 3) && issue.due_date <= Date.today)}
135 135 end
136 136
137 137 def test_operator_more_than_ago
138 138 Issue.find(7).update_attribute(:due_date, (Date.today - 10))
139 139 query = Query.new(:project => Project.find(1), :name => '_')
140 140 query.add_filter('due_date', '<t-', ['10'])
141 141 assert query.statement.include?("#{Issue.table_name}.due_date <=")
142 142 issues = find_issues_with_query(query)
143 143 assert !issues.empty?
144 144 issues.each {|issue| assert(issue.due_date <= (Date.today - 10))}
145 145 end
146 146
147 147 def test_operator_in
148 148 Issue.find(7).update_attribute(:due_date, (Date.today + 2))
149 149 query = Query.new(:project => Project.find(1), :name => '_')
150 150 query.add_filter('due_date', 't+', ['2'])
151 151 issues = find_issues_with_query(query)
152 152 assert !issues.empty?
153 153 issues.each {|issue| assert_equal((Date.today + 2), issue.due_date)}
154 154 end
155 155
156 156 def test_operator_ago
157 157 Issue.find(7).update_attribute(:due_date, (Date.today - 3))
158 158 query = Query.new(:project => Project.find(1), :name => '_')
159 159 query.add_filter('due_date', 't-', ['3'])
160 160 issues = find_issues_with_query(query)
161 161 assert !issues.empty?
162 162 issues.each {|issue| assert_equal((Date.today - 3), issue.due_date)}
163 163 end
164 164
165 165 def test_operator_today
166 166 query = Query.new(:project => Project.find(1), :name => '_')
167 167 query.add_filter('due_date', 't', [''])
168 168 issues = find_issues_with_query(query)
169 169 assert !issues.empty?
170 170 issues.each {|issue| assert_equal Date.today, issue.due_date}
171 171 end
172 172
173 173 def test_operator_this_week_on_date
174 174 query = Query.new(:project => Project.find(1), :name => '_')
175 175 query.add_filter('due_date', 'w', [''])
176 176 find_issues_with_query(query)
177 177 end
178 178
179 179 def test_operator_this_week_on_datetime
180 180 query = Query.new(:project => Project.find(1), :name => '_')
181 181 query.add_filter('created_on', 'w', [''])
182 182 find_issues_with_query(query)
183 183 end
184 184
185 185 def test_operator_contains
186 186 query = Query.new(:project => Project.find(1), :name => '_')
187 187 query.add_filter('subject', '~', ['uNable'])
188 188 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'")
189 189 result = find_issues_with_query(query)
190 190 assert result.empty?
191 191 result.each {|issue| assert issue.subject.downcase.include?('unable') }
192 192 end
193 193
194 194 def test_operator_does_not_contains
195 195 query = Query.new(:project => Project.find(1), :name => '_')
196 196 query.add_filter('subject', '!~', ['uNable'])
197 197 assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'")
198 198 find_issues_with_query(query)
199 199 end
200 200
201 201 def test_filter_watched_issues
202 202 User.current = User.find(1)
203 203 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '=', :values => ['me']}})
204 204 result = find_issues_with_query(query)
205 205 assert_not_nil result
206 206 assert !result.empty?
207 207 assert_equal Issue.visible.watched_by(User.current).sort_by(&:id), result.sort_by(&:id)
208 208 User.current = nil
209 209 end
210 210
211 211 def test_filter_unwatched_issues
212 212 User.current = User.find(1)
213 213 query = Query.new(:name => '_', :filters => { 'watcher_id' => {:operator => '!', :values => ['me']}})
214 214 result = find_issues_with_query(query)
215 215 assert_not_nil result
216 216 assert !result.empty?
217 217 assert_equal((Issue.visible - Issue.watched_by(User.current)).sort_by(&:id).size, result.sort_by(&:id).size)
218 218 User.current = nil
219 219 end
220 220
221 221 def test_default_columns
222 222 q = Query.new
223 223 assert !q.columns.empty?
224 224 end
225 225
226 226 def test_set_column_names
227 227 q = Query.new
228 228 q.column_names = ['tracker', :subject, '', 'unknonw_column']
229 229 assert_equal [:tracker, :subject], q.columns.collect {|c| c.name}
230 230 c = q.columns.first
231 231 assert q.has_column?(c)
232 232 end
233 233
234 234 def test_groupable_columns_should_include_custom_fields
235 235 q = Query.new
236 236 assert q.groupable_columns.detect {|c| c.is_a? QueryCustomFieldColumn}
237 237 end
238 238
239 239 def test_default_sort
240 240 q = Query.new
241 241 assert_equal [], q.sort_criteria
242 242 end
243 243
244 244 def test_set_sort_criteria_with_hash
245 245 q = Query.new
246 246 q.sort_criteria = {'0' => ['priority', 'desc'], '2' => ['tracker']}
247 247 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
248 248 end
249 249
250 250 def test_set_sort_criteria_with_array
251 251 q = Query.new
252 252 q.sort_criteria = [['priority', 'desc'], 'tracker']
253 253 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
254 254 end
255 255
256 256 def test_create_query_with_sort
257 257 q = Query.new(:name => 'Sorted')
258 258 q.sort_criteria = [['priority', 'desc'], 'tracker']
259 259 assert q.save
260 260 q.reload
261 261 assert_equal [['priority', 'desc'], ['tracker', 'asc']], q.sort_criteria
262 262 end
263 263
264 264 def test_sort_by_string_custom_field_asc
265 265 q = Query.new
266 266 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
267 267 assert c
268 268 assert c.sortable
269 269 issues = Issue.find :all,
270 270 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
271 271 :conditions => q.statement,
272 272 :order => "#{c.sortable} ASC"
273 273 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
274 274 assert !values.empty?
275 275 assert_equal values.sort, values
276 276 end
277 277
278 278 def test_sort_by_string_custom_field_desc
279 279 q = Query.new
280 280 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'string' }
281 281 assert c
282 282 assert c.sortable
283 283 issues = Issue.find :all,
284 284 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
285 285 :conditions => q.statement,
286 286 :order => "#{c.sortable} DESC"
287 287 values = issues.collect {|i| i.custom_value_for(c.custom_field).to_s}
288 288 assert !values.empty?
289 289 assert_equal values.sort.reverse, values
290 290 end
291 291
292 292 def test_sort_by_float_custom_field_asc
293 293 q = Query.new
294 294 c = q.available_columns.find {|col| col.is_a?(QueryCustomFieldColumn) && col.custom_field.field_format == 'float' }
295 295 assert c
296 296 assert c.sortable
297 297 issues = Issue.find :all,
298 298 :include => [ :assigned_to, :status, :tracker, :project, :priority ],
299 299 :conditions => q.statement,
300 300 :order => "#{c.sortable} ASC"
301 301 values = issues.collect {|i| begin; Kernel.Float(i.custom_value_for(c.custom_field).to_s); rescue; nil; end}.compact
302 302 assert !values.empty?
303 303 assert_equal values.sort, values
304 304 end
305 305
306 306 def test_invalid_query_should_raise_query_statement_invalid_error
307 307 q = Query.new
308 308 assert_raise Query::StatementInvalid do
309 309 q.issues(:conditions => "foo = 1")
310 310 end
311 311 end
312 312
313 313 def test_issue_count_by_association_group
314 314 q = Query.new(:name => '_', :group_by => 'assigned_to')
315 315 count_by_group = q.issue_count_by_group
316 316 assert_kind_of Hash, count_by_group
317 317 assert_equal %w(NilClass User), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
318 318 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
319 319 assert count_by_group.has_key?(User.find(3))
320 320 end
321 321
322 322 def test_issue_count_by_list_custom_field_group
323 323 q = Query.new(:name => '_', :group_by => 'cf_1')
324 324 count_by_group = q.issue_count_by_group
325 325 assert_kind_of Hash, count_by_group
326 326 assert_equal %w(NilClass String), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
327 327 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
328 328 assert count_by_group.has_key?('MySQL')
329 329 end
330 330
331 331 def test_issue_count_by_date_custom_field_group
332 332 q = Query.new(:name => '_', :group_by => 'cf_8')
333 333 count_by_group = q.issue_count_by_group
334 334 assert_kind_of Hash, count_by_group
335 335 assert_equal %w(Date NilClass), count_by_group.keys.collect {|k| k.class.name}.uniq.sort
336 336 assert_equal %w(Fixnum), count_by_group.values.collect {|k| k.class.name}.uniq
337 337 end
338 338
339 339 def test_label_for
340 340 q = Query.new
341 341 assert_equal 'assigned_to', q.label_for('assigned_to_id')
342 342 end
343 343
344 344 def test_editable_by
345 345 admin = User.find(1)
346 346 manager = User.find(2)
347 347 developer = User.find(3)
348 348
349 349 # Public query on project 1
350 350 q = Query.find(1)
351 351 assert q.editable_by?(admin)
352 352 assert q.editable_by?(manager)
353 353 assert !q.editable_by?(developer)
354 354
355 355 # Private query on project 1
356 356 q = Query.find(2)
357 357 assert q.editable_by?(admin)
358 358 assert !q.editable_by?(manager)
359 359 assert q.editable_by?(developer)
360 360
361 361 # Private query for all projects
362 362 q = Query.find(3)
363 363 assert q.editable_by?(admin)
364 364 assert !q.editable_by?(manager)
365 365 assert q.editable_by?(developer)
366 366
367 367 # Public query for all projects
368 368 q = Query.find(4)
369 369 assert q.editable_by?(admin)
370 370 assert !q.editable_by?(manager)
371 371 assert !q.editable_by?(developer)
372 372 end
373 373
374 374 context "#available_filters" do
375 375 setup do
376 376 @query = Query.new(:name => "_")
377 377 end
378 378
379 379 should "include users of visible projects in cross-project view" do
380 380 users = @query.available_filters["assigned_to_id"]
381 381 assert_not_nil users
382 382 assert users[:values].map{|u|u[1]}.include?("3")
383 383 end
384 384
385 385 context "'member_of_group' filter" do
386 386 should "be present" do
387 387 assert @query.available_filters.keys.include?("member_of_group")
388 388 end
389 389
390 390 should "be an optional list" do
391 391 assert_equal :list_optional, @query.available_filters["member_of_group"][:type]
392 392 end
393 393
394 394 should "have a list of the groups as values" do
395 395 Group.destroy_all # No fixtures
396 396 group1 = Group.generate!.reload
397 397 group2 = Group.generate!.reload
398 398
399 399 expected_group_list = [
400 400 [group1.name, group1.id],
401 401 [group2.name, group2.id]
402 402 ]
403 assert_equal expected_group_list, @query.available_filters["member_of_group"][:values]
403 assert_equal expected_group_list.sort, @query.available_filters["member_of_group"][:values].sort
404 404 end
405 405
406 406 end
407 407
408 408 context "'assigned_to_role' filter" do
409 409 should "be present" do
410 410 assert @query.available_filters.keys.include?("assigned_to_role")
411 411 end
412 412
413 413 should "be an optional list" do
414 414 assert_equal :list_optional, @query.available_filters["assigned_to_role"][:type]
415 415 end
416 416
417 417 should "have a list of the Roles as values" do
418 418 assert @query.available_filters["assigned_to_role"][:values].include?(['Manager',1])
419 419 assert @query.available_filters["assigned_to_role"][:values].include?(['Developer',2])
420 420 assert @query.available_filters["assigned_to_role"][:values].include?(['Reporter',3])
421 421 end
422 422
423 423 should "not include the built in Roles as values" do
424 424 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Non member',4])
425 425 assert ! @query.available_filters["assigned_to_role"][:values].include?(['Anonymous',5])
426 426 end
427 427
428 428 end
429 429
430 430 end
431 431
432 432 context "#statement" do
433 433 context "with 'member_of_group' filter" do
434 434 setup do
435 435 Group.destroy_all # No fixtures
436 436 @user_in_group = User.generate!
437 437 @second_user_in_group = User.generate!
438 438 @user_in_group2 = User.generate!
439 439 @user_not_in_group = User.generate!
440 440
441 441 @group = Group.generate!.reload
442 442 @group.users << @user_in_group
443 443 @group.users << @second_user_in_group
444 444
445 445 @group2 = Group.generate!.reload
446 446 @group2.users << @user_in_group2
447 447
448 448 end
449 449
450 450 should "search assigned to for users in the group" do
451 451 @query = Query.new(:name => '_')
452 452 @query.add_filter('member_of_group', '=', [@group.id.to_s])
453 453
454 454 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@user_in_group.id}','#{@second_user_in_group.id}')"
455 455 assert_find_issues_with_query_is_successful @query
456 456 end
457 457
458 458 should "search not assigned to any group member (none)" do
459 459 @query = Query.new(:name => '_')
460 460 @query.add_filter('member_of_group', '!*', [''])
461 461
462 462 # Users not in a group
463 463 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}')"
464 464 assert_find_issues_with_query_is_successful @query
465 465
466 466 end
467 467
468 468 should "search assigned to any group member (all)" do
469 469 @query = Query.new(:name => '_')
470 470 @query.add_filter('member_of_group', '*', [''])
471 471
472 472 # Only users in a group
473 473 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}')"
474 474 assert_find_issues_with_query_is_successful @query
475 475
476 476 end
477 477 end
478 478
479 479 context "with 'assigned_to_role' filter" do
480 480 setup do
481 481 # No fixtures
482 482 MemberRole.delete_all
483 483 Member.delete_all
484 484 Role.delete_all
485 485
486 486 @manager_role = Role.generate!(:name => 'Manager')
487 487 @developer_role = Role.generate!(:name => 'Developer')
488 488
489 489 @project = Project.generate!
490 490 @manager = User.generate!
491 491 @developer = User.generate!
492 492 @boss = User.generate!
493 493 User.add_to_project(@manager, @project, @manager_role)
494 494 User.add_to_project(@developer, @project, @developer_role)
495 495 User.add_to_project(@boss, @project, [@manager_role, @developer_role])
496 496 end
497 497
498 498 should "search assigned to for users with the Role" do
499 499 @query = Query.new(:name => '_')
500 500 @query.add_filter('assigned_to_role', '=', [@manager_role.id.to_s])
501 501
502 502 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@manager.id}','#{@boss.id}')"
503 503 assert_find_issues_with_query_is_successful @query
504 504 end
505 505
506 506 should "search assigned to for users not assigned to any Role (none)" do
507 507 @query = Query.new(:name => '_')
508 508 @query.add_filter('assigned_to_role', '!*', [''])
509 509
510 510 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}')"
511 511 assert_find_issues_with_query_is_successful @query
512 512 end
513 513
514 514 should "search assigned to for users assigned to any Role (all)" do
515 515 @query = Query.new(:name => '_')
516 516 @query.add_filter('assigned_to_role', '*', [''])
517 517
518 518 assert_query_statement_includes @query, "#{Issue.table_name}.assigned_to_id IN ('#{@manager.id}','#{@developer.id}','#{@boss.id}')"
519 519 assert_find_issues_with_query_is_successful @query
520 520 end
521 521 end
522 522 end
523 523
524 524 end
General Comments 0
You need to be logged in to leave comments. Login now