meta_search_hub 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,969 @@
1
+ require 'helper'
2
+
3
+ class TestSearch < Test::Unit::TestCase
4
+
5
+ context "A Company search where options[:user] = 'blocked'" do
6
+ setup do
7
+ @s = Company.search({}, :user => 'blocked')
8
+ end
9
+
10
+ should "not respond_to? a search against backwards_name" do
11
+ assert !@s.respond_to?(:backwards_name), "The search responded to :backwards_name"
12
+ end
13
+
14
+ should "raise an error if we try to search on backwards_name" do
15
+ assert_raise NoMethodError do
16
+ @s.backwards_name = 'blah'
17
+ end
18
+ end
19
+
20
+ should "not respond_to? a search against updated_at_eq" do
21
+ assert !@s.respond_to?(:updated_at_eq), "The search responded to :updated_at_eq"
22
+ end
23
+
24
+ should "raise an error if we try to search on updated_at" do
25
+ assert_raise NoMethodError do
26
+ @s.updated_at_eq = 'blah'
27
+ end
28
+ end
29
+
30
+ should "not respond_to? a search against notes_note_matches" do
31
+ assert !@s.respond_to?(:notes_note_matches), "The search responded to :notes_note_matches"
32
+ end
33
+
34
+ should "raise an error if we try to search on notes_note_matches" do
35
+ assert_raise NoMethodError do
36
+ @s.notes_note_matches = '%blah%'
37
+ end
38
+ end
39
+ end
40
+
41
+ context "A Developer search where options[:user] = 'privileged'" do
42
+ setup do
43
+ @s = Developer.search({}, :user => 'privileged')
44
+ end
45
+
46
+ should "respond_to? a search against name_eq" do
47
+ assert_respond_to @s, :name_eq
48
+ end
49
+
50
+ should "not raise an error on a search against name_eq" do
51
+ assert_nothing_raised do
52
+ @s.name_eq = 'blah'
53
+ end
54
+ end
55
+
56
+ should "respond_to? a search against company_name_eq" do
57
+ assert_respond_to @s, :company_name_eq
58
+ end
59
+
60
+ should "not raise an error on a search against name_eq" do
61
+ assert_nothing_raised do
62
+ @s.company_name_eq = 'blah'
63
+ end
64
+ end
65
+
66
+ should "respond_to? a search against company_updated_at_eq" do
67
+ assert_respond_to @s, :company_updated_at_eq
68
+ end
69
+
70
+ should "not raise an error on a search against company_updated_at_eq" do
71
+ assert_nothing_raised do
72
+ @s.company_updated_at_eq = Time.now
73
+ end
74
+ end
75
+ end
76
+
77
+ context "A Developer search" do
78
+ setup do
79
+ @s = Developer.search({:name_equals=>"Forgetful Notetaker"})
80
+ end
81
+
82
+ context "without any opts" do
83
+ should "find a null entry when searching notes" do
84
+ assert_equal 1, @s.notes_note_is_null(true).all.size
85
+ end
86
+
87
+ should "find no non-null entry when searching notes" do
88
+ assert_equal 0, @s.notes_note_is_not_null(true).all.size
89
+ end
90
+ end
91
+
92
+ context "with outer join specified" do
93
+ setup do
94
+ @s = Developer.search({:name_equals => "Forgetful Notetaker"}, :join_type => :outer)
95
+ end
96
+
97
+ should "find a null entry when searching notes" do
98
+ assert_equal 1, @s.notes_note_is_null(true).all.size
99
+ end
100
+
101
+ should "find no non-null entry when searching notes" do
102
+ assert_equal 0, @s.notes_note_is_not_null(true).all.size
103
+ end
104
+ end
105
+
106
+ context "with inner join specified" do
107
+ setup do
108
+ @s = Developer.search({:name_equals=>"Forgetful Notetaker"}, :join_type => :inner)
109
+ end
110
+
111
+ should "find no null entry when searching notes" do
112
+ assert_equal 0, @s.notes_note_is_null(true).all.size
113
+ end
114
+
115
+ should "find no non-null entry when searching notes" do
116
+ assert_equal 0, @s.notes_note_is_not_null(true).all.size
117
+ end
118
+ end
119
+
120
+
121
+ end
122
+
123
+ [{:name => 'Company', :object => Company},
124
+ {:name => 'Company as a Relation', :object => Company.scoped}].each do |object|
125
+ context_a_search_against object[:name], object[:object] do
126
+ should "have a relation attribute which is an ActiveRecord::Relation" do
127
+ assert_equal ActiveRecord::Relation, @s.relation.class
128
+ end
129
+
130
+ should "have a base attribute which is a Class inheriting from ActiveRecord::Base" do
131
+ assert_equal Company, @s.base
132
+ assert_contains @s.base.ancestors, ActiveRecord::Base
133
+ end
134
+
135
+ should "have an association named developers" do
136
+ assert @s.get_association(:developers)
137
+ end
138
+
139
+ should "respond_to? a search against a developer attribute" do
140
+ assert_respond_to @s, :developers_name_eq
141
+ end
142
+
143
+ should "have a column named name" do
144
+ assert @s.get_column(:name)
145
+ end
146
+
147
+ should "respond_to? a search against name" do
148
+ assert_respond_to @s, :name_eq
149
+ end
150
+
151
+ should "respond_to? a search against backwards_name" do
152
+ assert_respond_to @s, :backwards_name
153
+ end
154
+
155
+ should "exclude the column named updated_at" do
156
+ assert_nil @s.get_column(:updated_at)
157
+ end
158
+
159
+ should "not respond_to? updated_at" do
160
+ assert !@s.respond_to?(:updated_at), "The search responded to :updated_at"
161
+ end
162
+
163
+ should "raise an error if we try to search on updated_at" do
164
+ assert_raise NoMethodError do
165
+ @s.updated_at_eq = [2009, 1, 1]
166
+ end
167
+ end
168
+
169
+ should "exclude the association named notes" do
170
+ assert_nil @s.get_association(:notes)
171
+ end
172
+
173
+ should "not respond_to? notes_note_eq" do
174
+ assert !@s.respond_to?(:notes_note_eq), "The search responded to :notes_note_eq"
175
+ end
176
+
177
+ should "raise an error if we try to search on notes" do
178
+ assert_raise NoMethodError do
179
+ @s.notes_note_eq = 'Blah'
180
+ end
181
+ end
182
+
183
+ should "honor its associations' excluded attributes" do
184
+ assert_nil @s.get_attribute(:data_types_str)
185
+ end
186
+
187
+ should "not respond_to? data_types_str_eq" do
188
+ assert !@s.respond_to?(:data_types_str_eq), "The search responded to :data_types_str_eq"
189
+ end
190
+
191
+ should "respond_to? data_types_bln_eq" do
192
+ assert_respond_to @s, :data_types_bln_eq
193
+ end
194
+
195
+ should "raise an error if we try to search data_types.str" do
196
+ assert_raise NoMethodError do
197
+ @s.data_types_str_eq = 'Blah'
198
+ end
199
+ end
200
+
201
+ should "raise an error when MAX_JOIN_DEPTH is exceeded" do
202
+ assert_raise MetaSearch::JoinDepthError do
203
+ @s.developers_company_developers_company_developers_name_equals = "Ernie Miller"
204
+ end
205
+ end
206
+
207
+ context "when meta_sort value is empty string" do
208
+ setup do
209
+ @s.meta_sort = ''
210
+ end
211
+
212
+ should "not raise an error, just ignore sorting" do
213
+ assert_nothing_raised do
214
+ assert_equal Company.all, @s.all
215
+ end
216
+ end
217
+ end
218
+
219
+ should "sort by name in ascending order" do
220
+ @s.meta_sort = 'name.asc'
221
+ assert_equal Company.order('name asc').all,
222
+ @s.all
223
+ end
224
+
225
+ should "sort by name in ascending order as a method call" do
226
+ @s.meta_sort 'name.asc'
227
+ assert_equal Company.order('name asc').all,
228
+ @s.all
229
+ end
230
+
231
+ should "sort by name in descending order" do
232
+ @s.meta_sort = 'name.desc'
233
+ assert_equal Company.order('name desc').all,
234
+ @s.all
235
+ end
236
+
237
+ context "where name contains optical" do
238
+ setup do
239
+ @s.name_contains = 'optical'
240
+ end
241
+
242
+ should "return one result" do
243
+ assert_equal 1, @s.all.size
244
+ end
245
+
246
+ should "return a company named Advanced Optical Solutions" do
247
+ assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
248
+ end
249
+
250
+ should "not return a company named Initech" do
251
+ assert_does_not_contain @s.all, Company.where(:name => "Initech").first
252
+ end
253
+ end
254
+
255
+ context "where name contains optical as a method call" do
256
+ setup do
257
+ @s.name_contains 'optical'
258
+ end
259
+
260
+ should "return one result" do
261
+ assert_equal 1, @s.all.size
262
+ end
263
+
264
+ should "return a company named Advanced Optical Solutions" do
265
+ assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
266
+ end
267
+
268
+ should "not return a company named Initech" do
269
+ assert_does_not_contain @s.all, Company.where(:name => "Initech").first
270
+ end
271
+ end
272
+
273
+ context "where developer name starts with Ernie" do
274
+ setup do
275
+ @s.developers_name_starts_with = 'Ernie'
276
+ end
277
+
278
+ should "return one result" do
279
+ assert_equal 1, @s.all.size
280
+ end
281
+
282
+ should "return a company named Mission Data" do
283
+ assert_contains @s.all, Company.where(:name => 'Mission Data').first
284
+ end
285
+
286
+ should "not return a company named Initech" do
287
+ assert_does_not_contain @s.all, Company.where(:name => "Initech").first
288
+ end
289
+
290
+ context "and slackers salary is greater than $70k" do
291
+ setup do
292
+ @s.slackers_salary_gt = 70000
293
+ end
294
+
295
+ should "return no results" do
296
+ assert_equal 0, @s.all.size
297
+ end
298
+
299
+ should "join developers twice" do
300
+ assert @s.to_sql.match(/join\s+"?developers"?.*join\s+"?developers"?/i)
301
+ end
302
+
303
+ should "alias the second join of developers" do
304
+ assert @s.to_sql.match(/join\s+"?developers"?\s+"?slackers_companies"?/i)
305
+ end
306
+ end
307
+ end
308
+
309
+ context "where developer note indicates he will crack yo skull" do
310
+ setup do
311
+ @s.developer_notes_note_equals = "Will show you what he's doing."
312
+ end
313
+
314
+ should "return one result" do
315
+ assert_equal 1, @s.all.size
316
+ end
317
+
318
+ should "return a company named Advanced Optical Solutions" do
319
+ assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
320
+ end
321
+
322
+ should "not return a company named Mission Data" do
323
+ assert_does_not_contain @s.all, Company.where(:name => "Mission Data").first
324
+ end
325
+ end
326
+
327
+ context "where developer note indicates he will crack yo skull through two associations" do
328
+ setup do
329
+ @s.developers_notes_note_equals = "Will show you what he's doing."
330
+ end
331
+
332
+ should "return one result" do
333
+ assert_equal 1, @s.all.size
334
+ end
335
+
336
+ should "return a company named Advanced Optical Solutions" do
337
+ assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
338
+ end
339
+
340
+ should "not return a company named Mission Data" do
341
+ assert_does_not_contain @s.all, Company.where(:name => "Mission Data").first
342
+ end
343
+ end
344
+
345
+ context "where developer note indicates he will crack yo skull through four associations" do
346
+ setup do
347
+ @s.developers_company_developers_notes_note_equals = "Will show you what he's doing."
348
+ end
349
+
350
+ should "return two results, one of which is a duplicate due to joins" do
351
+ assert_equal 2, @s.all.size
352
+ assert_equal 1, @s.all.uniq.size
353
+ end
354
+
355
+ should "return a company named Advanced Optical Solutions" do
356
+ assert_contains @s.all, Company.where(:name => 'Advanced Optical Solutions').first
357
+ end
358
+
359
+ should "not return a company named Mission Data" do
360
+ assert_does_not_contain @s.all, Company.where(:name => "Mission Data").first
361
+ end
362
+ end
363
+
364
+ context "where backwards name is hcetinI as a method call" do
365
+ setup do
366
+ @s.backwards_name 'hcetinI'
367
+ end
368
+
369
+ should "return 1 result" do
370
+ assert_equal 1, @s.all.size
371
+ end
372
+
373
+ should "return a company named Initech" do
374
+ assert_contains @s.all, Company.where(:name => 'Initech').first
375
+ end
376
+ end
377
+
378
+ context "where backwards name is hcetinI" do
379
+ setup do
380
+ @s.backwards_name = 'hcetinI'
381
+ end
382
+
383
+ should "return 1 result" do
384
+ assert_equal 1, @s.all.size
385
+ end
386
+
387
+ should "return a company named Initech" do
388
+ assert_contains @s.all, Company.where(:name => 'Initech').first
389
+ end
390
+ end
391
+
392
+ context "where with_slackers_by_name_and_salary_range is sent an array with 3 values" do
393
+ setup do
394
+ @s.with_slackers_by_name_and_salary_range = ['Peter Gibbons', 90000, 110000]
395
+ end
396
+
397
+ should "return 1 result" do
398
+ assert_equal 1, @s.all.size
399
+ end
400
+
401
+ should "return a company named Initech" do
402
+ assert_contains @s.all, Company.where(:name => 'Initech').first
403
+ end
404
+ end
405
+
406
+ should "raise an error when the wrong number of parameters would be supplied to a custom search" do
407
+ assert_raise ArgumentError do
408
+ @s.with_slackers_by_name_and_salary_range = ['Peter Gibbons', 90000]
409
+ end
410
+ end
411
+
412
+ should "raise an error when a custom search method does not return a relation" do
413
+ assert_raise MetaSearch::NonRelationReturnedError do
414
+ @s.backwards_name_as_string = 'hcetinI'
415
+ end
416
+ end
417
+ end
418
+ end
419
+
420
+ [{:name => 'Developer', :object => Developer},
421
+ {:name => 'Developer as a Relation', :object => Developer.scoped}].each do |object|
422
+ context_a_search_against object[:name], object[:object] do
423
+ should "exclude the column named company_id" do
424
+ assert_nil @s.get_column(:company_id)
425
+ end
426
+
427
+ should "have an association named projects" do
428
+ assert @s.get_association(:projects)
429
+ end
430
+
431
+ context "sorted by company name in ascending order" do
432
+ setup do
433
+ @s.meta_sort = 'company_name.asc'
434
+ end
435
+
436
+ should "sort by company name in ascending order" do
437
+ assert_equal Developer.joins(:company).order('companies.name asc').all,
438
+ @s.all
439
+ end
440
+ end
441
+
442
+ context "sorted by company name in descending order" do
443
+ setup do
444
+ @s.meta_sort = 'company_name.desc'
445
+ end
446
+
447
+ should "sort by company name in descending order" do
448
+ assert_equal Developer.joins(:company).order('companies.name desc').all,
449
+ @s.all
450
+ end
451
+ end
452
+
453
+ context "sorted by salary and name in descending order" do
454
+ setup do
455
+ @s.meta_sort = 'salary_and_name.desc'
456
+ end
457
+
458
+ should "sort by salary and name in descending order" do
459
+ assert_equal Developer.order('salary DESC, name DESC').all,
460
+ @s.all
461
+ end
462
+ end
463
+
464
+ context "where developer is Bob-approved" do
465
+ setup do
466
+ @s.notes_note_equals = "A straight shooter with upper management written all over him."
467
+ end
468
+
469
+ should "return Peter Gibbons" do
470
+ assert_contains @s.all, Developer.where(:name => 'Peter Gibbons').first
471
+ end
472
+ end
473
+
474
+ context "where name or company name starts with m" do
475
+ setup do
476
+ @s.name_or_company_name_starts_with = "m"
477
+ end
478
+
479
+ should "return Michael Bolton and all employees of Mission Data" do
480
+ assert_equal @s.all, Developer.where(:name => 'Michael Bolton').all +
481
+ Company.where(:name => 'Mission Data').first.developers
482
+ end
483
+ end
484
+
485
+ context "where name ends with Miller" do
486
+ setup do
487
+ @s.name_ends_with = 'Miller'
488
+ end
489
+
490
+ should "return one result" do
491
+ assert_equal 1, @s.all.size
492
+ end
493
+
494
+ should "return a developer named Ernie Miller" do
495
+ assert_contains @s.all, Developer.where(:name => 'Ernie Miller').first
496
+ end
497
+
498
+ should "not return a developer named Herb Myers" do
499
+ assert_does_not_contain @s.all, Developer.where(:name => "Herb Myers").first
500
+ end
501
+ end
502
+
503
+ context "where name starts with any of Ernie, Herb, or Peter" do
504
+ setup do
505
+ @s.name_starts_with_any = ['Ernie', 'Herb', 'Peter']
506
+ end
507
+
508
+ should "return three results" do
509
+ assert_equal 3, @s.all.size
510
+ end
511
+
512
+ should "return a developer named Ernie Miller" do
513
+ assert_contains @s.all, Developer.where(:name => 'Ernie Miller').first
514
+ end
515
+
516
+ should "not return a developer named Samir Nagheenanajar" do
517
+ assert_does_not_contain @s.all, Developer.where(:name => "Samir Nagheenanajar").first
518
+ end
519
+ end
520
+
521
+ context "where name does not equal Ernie Miller" do
522
+ setup do
523
+ @s.name_ne = 'Ernie Miller'
524
+ end
525
+
526
+ should "return eight results" do
527
+ assert_equal 8, @s.all.size
528
+ end
529
+
530
+ should "not return a developer named Ernie Miller" do
531
+ assert_does_not_contain @s.all, Developer.where(:name => "Ernie Miller").first
532
+ end
533
+ end
534
+
535
+ context "where name contains all of a, e, and i" do
536
+ setup do
537
+ @s.name_contains_all = ['a', 'e', 'i']
538
+ end
539
+
540
+ should "return two results" do
541
+ assert_equal 2, @s.all.size
542
+ end
543
+
544
+ should "return a developer named Samir Nagheenanajar" do
545
+ assert_contains @s.all, Developer.where(:name => "Samir Nagheenanajar").first
546
+ end
547
+
548
+ should "not return a developer named Ernie Miller" do
549
+ assert_does_not_contain @s.all, Developer.where(:name => 'Ernie Miller').first
550
+ end
551
+ end
552
+
553
+ context "where project estimated hours are greater than or equal to 1000" do
554
+ setup do
555
+ @s.projects_estimated_hours_gte = 1000
556
+ end
557
+
558
+ should "return three results" do
559
+ assert_equal 3, @s.all.size
560
+ end
561
+
562
+ should "return these developers" do
563
+ assert_same_elements @s.all.collect {|d| d.name},
564
+ ['Peter Gibbons', 'Michael Bolton', 'Samir Nagheenanajar']
565
+ end
566
+ end
567
+
568
+ context "where project estimated hours are greater than 1000" do
569
+ setup do
570
+ @s.projects_estimated_hours_gt = 1000
571
+ end
572
+
573
+ should "return no results" do
574
+ assert_equal 0, @s.all.size
575
+ end
576
+ end
577
+
578
+ context "where developer is named Ernie Miller by polymorphic belongs_to against an association" do
579
+ setup do
580
+ @s.notes_notable_developer_type_name_equals = "Ernie Miller"
581
+ end
582
+
583
+ should "return one result" do
584
+ assert_equal 1, @s.all.size
585
+ end
586
+
587
+ should "return a developer named Ernie Miller" do
588
+ assert_contains @s.all, Developer.where(:name => 'Ernie Miller').first
589
+ end
590
+
591
+ should "not return a developer named Herb Myers" do
592
+ assert_does_not_contain @s.all, Developer.where(:name => "Herb Myers").first
593
+ end
594
+ end
595
+ end
596
+ end
597
+
598
+ [{:name => 'DataType', :object => DataType},
599
+ {:name => 'DataType as a Relation', :object => DataType.scoped}].each do |object|
600
+ context_a_search_against object[:name], object[:object] do
601
+ should "raise an error on a contains search against a boolean column" do
602
+ assert_raise NoMethodError do
603
+ @s.bln_contains = "true"
604
+ end
605
+ end
606
+
607
+ context "where boolean column equals true" do
608
+ setup do
609
+ @s.bln_equals = true
610
+ end
611
+
612
+ should "return five results" do
613
+ assert_equal 5, @s.all.size
614
+ end
615
+
616
+ should "contain no results with a false boolean column" do
617
+ assert_does_not_contain @s.all.collect {|r| r.bln}, false
618
+ end
619
+ end
620
+
621
+ context "where boolean column is_true" do
622
+ setup do
623
+ @s.bln_is_true = true
624
+ end
625
+
626
+ should "return five results" do
627
+ assert_equal 5, @s.all.size
628
+ end
629
+
630
+ should "contain no results with a false boolean column" do
631
+ assert_does_not_contain @s.all.collect {|r| r.bln}, false
632
+ end
633
+ end
634
+
635
+ context "where boolean column equals false" do
636
+ setup do
637
+ @s.bln_equals = false
638
+ end
639
+
640
+ should "return four results" do
641
+ assert_equal 4, @s.all.size
642
+ end
643
+
644
+ should "contain no results with a true boolean column" do
645
+ assert_does_not_contain @s.all.collect {|r| r.bln}, true
646
+ end
647
+ end
648
+
649
+ context "where boolean column is_false" do
650
+ setup do
651
+ @s.bln_is_false = true
652
+ end
653
+
654
+ should "return four results" do
655
+ assert_equal 4, @s.all.size
656
+ end
657
+
658
+ should "contain no results with a true boolean column" do
659
+ assert_does_not_contain @s.all.collect {|r| r.bln}, true
660
+ end
661
+ end
662
+
663
+ context "where date column is Christmas 2009 by array" do
664
+ setup do
665
+ @s.dat_equals = [2009, 12, 25]
666
+ end
667
+
668
+ should "return one result" do
669
+ assert_equal 1, @s.all.size
670
+ end
671
+
672
+ should "contain a result with Christmas 2009 as its date" do
673
+ assert_equal Date.parse('2009/12/25'), @s.first.dat
674
+ end
675
+ end
676
+
677
+ context "where date column is Christmas 2009 by Date object" do
678
+ setup do
679
+ @s.dat_equals = Date.new(2009, 12, 25)
680
+ end
681
+
682
+ should "return one result" do
683
+ assert_equal 1, @s.all.size
684
+ end
685
+
686
+ should "contain a result with Christmas 2009 as its date" do
687
+ assert_equal Date.parse('2009/12/25'), @s.first.dat
688
+ end
689
+ end
690
+
691
+ context "where time column is > 1:00 PM and < 3:30 PM" do
692
+ setup do
693
+ @s.tim_gt = Time.parse('2000-01-01 13:00') # Rails "dummy time" format
694
+ @s.tim_lt = Time.parse('2000-01-01 15:30') # Rails "dummy time" format
695
+ end
696
+
697
+ should "return three results" do
698
+ assert_equal 3, @s.all.size
699
+ end
700
+
701
+ should "not contain results with time column before or after constraints" do
702
+ assert_equal [], @s.all.select {|r|
703
+ r.tim < Time.parse('2000-01-01 13:00') || r.tim > Time.parse('2000-01-01 15:30')
704
+ }
705
+ end
706
+ end
707
+
708
+ context "where timestamp column is in the year 2010" do
709
+ setup do
710
+ @s.tms_gte = Time.utc(2010, 1, 1)
711
+ end
712
+
713
+ should "return two results" do
714
+ assert_equal 2, @s.all.size
715
+ end
716
+
717
+ should "not contain results with timestamp column before 2010" do
718
+ assert_equal [], @s.all.select {|r|
719
+ r.tms < Time.utc(2010, 1, 1)
720
+ }
721
+ end
722
+ end
723
+
724
+ context "where timestamp column is before the year 2010" do
725
+ setup do
726
+ @s.tms_lt = Time.utc(2010, 1, 1)
727
+ end
728
+
729
+ should "return seven results" do
730
+ assert_equal 7, @s.all.size
731
+ end
732
+
733
+ should "not contain results with timestamp in 2010" do
734
+ assert_equal [], @s.all.select {|r|
735
+ r.tms >= Time.utc(2010, 1, 1)
736
+ }
737
+ end
738
+ end
739
+
740
+ context "where decimal column is > 5000" do
741
+ setup do
742
+ @s.dec_gt = 5000
743
+ end
744
+
745
+ should "return four results" do
746
+ assert_equal 4, @s.all.size
747
+ end
748
+
749
+ should "not contain results with decimal column <= 5000" do
750
+ assert_equal [], @s.all.select {|r|
751
+ r.dec <= 5000
752
+ }
753
+ end
754
+ end
755
+
756
+ context "where float column is between 2.5 and 3.5" do
757
+ setup do
758
+ @s.flt_gte = 2.5
759
+ @s.flt_lte = 3.5
760
+ end
761
+
762
+ should "return three results" do
763
+ assert_equal 3, @s.all.size
764
+ end
765
+
766
+ should "not contain results with float column outside constraints" do
767
+ assert_equal [], @s.all.select {|r|
768
+ r.flt < 2.5 || r.flt > 3.5
769
+ }
770
+ end
771
+ end
772
+
773
+ context "where integer column is in the set (1, 8, 729)" do
774
+ setup do
775
+ @s.int_in = [1, 8, 729]
776
+ end
777
+
778
+ should "return three results" do
779
+ assert_equal 3, @s.all.size
780
+ end
781
+
782
+ should "not contain results outside the specified set" do
783
+ assert_equal [], @s.all.select {|r|
784
+ ![1, 8, 729].include?(r.int)
785
+ }
786
+ end
787
+ end
788
+
789
+ context "where integer column is not in the set (1, 8, 729)" do
790
+ setup do
791
+ @s.int_not_in = [1, 8, 729]
792
+ end
793
+
794
+ should "return six results" do
795
+ assert_equal 6, @s.all.size
796
+ end
797
+
798
+ should "not contain results outside the specified set" do
799
+ assert_equal [], @s.all.reject {|r|
800
+ ![1, 8, 729].include?(r.int)
801
+ }
802
+ end
803
+ end
804
+ end
805
+ end
806
+
807
+ context_a_search_against "a relation with existing criteria and joins",
808
+ Company.where(:name => "Initech").joins(:developers) do
809
+ should "return the same results as a non-searched relation with no search terms" do
810
+ assert_equal Company.where(:name => "Initech").joins(:developers).all, @s.all
811
+ end
812
+
813
+ context "with a search against the joined association's data" do
814
+ setup do
815
+ @s.developers_salary_less_than = 75000
816
+ end
817
+
818
+ should "not ask to join the association twice" do
819
+ assert_equal 1, @s.relation.joins_values.size
820
+ end
821
+
822
+ should "return a filtered result set based on the criteria of the searched relation" do
823
+ assert_equal Company.where(:name => 'Initech').all, @s.all.uniq
824
+ end
825
+ end
826
+ end
827
+
828
+ context_a_search_against "a relation derived from a joined association",
829
+ Company.where(:name => "Initech").first.developers do
830
+ should "not raise an error" do
831
+ assert_nothing_raised do
832
+ @s.all
833
+ end
834
+ end
835
+
836
+ should "return all developers for that company without conditions" do
837
+ assert_equal Company.where(:name => 'Initech').first.developers.all, @s.all
838
+ end
839
+
840
+ should "allow conditions on the search" do
841
+ @s.name_equals = 'Peter Gibbons'
842
+ assert_equal Developer.where(:name => 'Peter Gibbons').first,
843
+ @s.first
844
+ end
845
+ end
846
+
847
+ context_a_search_against "a relation derived from a joined HM:T association",
848
+ Company.where(:name => "Initech").first.developer_notes do
849
+ should "not raise an error" do
850
+ assert_nothing_raised do
851
+ @s.all
852
+ end
853
+ end
854
+
855
+ should "return all developer notes for that company without conditions" do
856
+ assert_equal Company.where(:name => 'Initech').first.developer_notes.all, @s.all
857
+ end
858
+
859
+ should "allow conditions on the search" do
860
+ @s.note_equals = 'A straight shooter with upper management written all over him.'
861
+ assert_equal Note.where(:note => 'A straight shooter with upper management written all over him.').first,
862
+ @s.first
863
+ end
864
+ end
865
+
866
+ [{:name => 'Project', :object => Project},
867
+ {:name => 'Project as a Relation', :object => Project.scoped}].each do |object|
868
+ context_a_search_against object[:name], object[:object] do
869
+ context "where name is present" do
870
+ setup do
871
+ @s.name_is_present = true
872
+ end
873
+
874
+ should "return 5 results" do
875
+ assert_equal 5, @s.all.size
876
+ end
877
+
878
+ should "contain no results with a blank name column" do
879
+ assert_equal 0, @s.all.select {|r| r.name.blank?}.size
880
+ end
881
+ end
882
+
883
+ context "where name is blank" do
884
+ setup do
885
+ @s.name_is_blank = true
886
+ end
887
+
888
+ should "return 2 results" do
889
+ assert_equal 2, @s.all.size
890
+ end
891
+
892
+ should "contain no results with a present name column" do
893
+ assert_equal 0, @s.all.select {|r| r.name.present?}.size
894
+ end
895
+ end
896
+
897
+ context "where name is null" do
898
+ setup do
899
+ @s.name_is_null = true
900
+ end
901
+
902
+ should "return 1 result" do
903
+ assert_equal 1, @s.all.size
904
+ end
905
+
906
+ should "contain no results with a non-null name column" do
907
+ assert_equal 0, @s.all.select {|r| r.name != nil}.size
908
+ end
909
+ end
910
+
911
+ context "where name is not null" do
912
+ setup do
913
+ @s.name_is_not_null = true
914
+ end
915
+
916
+ should "return 6 results" do
917
+ assert_equal 6, @s.all.size
918
+ end
919
+
920
+ should "contain no results with a null name column" do
921
+ assert_equal 0, @s.all.select {|r| r.name = nil}.size
922
+ end
923
+ end
924
+
925
+ context "where notes_id is null" do
926
+ setup do
927
+ @s.notes_id_is_null = true
928
+ end
929
+
930
+ should "return 2 results" do
931
+ assert_equal 2, @s.all.size
932
+ end
933
+
934
+ should "contain no results with notes" do
935
+ assert_equal 0, @s.all.select {|r| r.notes.size > 0}.size
936
+ end
937
+ end
938
+ end
939
+ end
940
+
941
+ [{:name => 'Note', :object => Note},
942
+ {:name => 'Note as a Relation', :object => Note.scoped}].each do |object|
943
+ context_a_search_against object[:name], object[:object] do
944
+ should "allow search on polymorphic belongs_to associations" do
945
+ @s.notable_project_type_name_contains = 'MetaSearch'
946
+ assert_equal Project.find_by_name('MetaSearch Development').notes, @s.all
947
+ end
948
+
949
+ should "allow search on multiple polymorphic belongs_to associations" do
950
+ @s.notable_project_type_name_or_notable_developer_type_name_starts_with = 'M'
951
+ assert_equal Project.find_by_name('MetaSearch Development').notes +
952
+ Developer.find_by_name('Michael Bolton').notes,
953
+ @s.all
954
+ end
955
+
956
+ should "allow traversal of polymorphic associations" do
957
+ @s.notable_developer_type_company_name_starts_with = 'M'
958
+ assert_equal Company.find_by_name('Mission Data').developers.map(&:notes).flatten.sort {|a, b| a.id <=>b.id},
959
+ @s.all.sort {|a, b| a.id <=> b.id}
960
+ end
961
+
962
+ should "raise an error when attempting to search against polymorphic belongs_to association without a type" do
963
+ assert_raises ::MetaSearch::PolymorphicAssociationMissingTypeError do
964
+ @s.notable_name_contains = 'MetaSearch'
965
+ end
966
+ end
967
+ end
968
+ end
969
+ end