sunspot_matchers_testunit 1.0
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.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +27 -0
- data/MIT-LICENSE +21 -0
- data/README.markdown +238 -0
- data/Rakefile +11 -0
- data/lib/sunspot_matchers_testunit.rb +2 -0
- data/lib/sunspot_matchers_testunit/matchers.rb +317 -0
- data/lib/sunspot_matchers_testunit/sunspot_session_spy.rb +112 -0
- data/lib/sunspot_matchers_testunit/version.rb +3 -0
- data/sunspot_matchers_testunit.gemspec +21 -0
- data/test/sunspot_matchers_testunit_test.rb +702 -0
- metadata +121 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sunspot_matchers_testunit (1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
builder (3.0.0)
|
10
|
+
escape (0.0.4)
|
11
|
+
pr_geohash (1.0.0)
|
12
|
+
rake (0.8.7)
|
13
|
+
rsolr (0.12.1)
|
14
|
+
builder (>= 2.1.2)
|
15
|
+
sunspot (1.2.1)
|
16
|
+
escape (= 0.0.4)
|
17
|
+
pr_geohash (~> 1.0)
|
18
|
+
rsolr (= 0.12.1)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
bundler (>= 1.0.0)
|
25
|
+
rake
|
26
|
+
sunspot (~> 1.2.1)
|
27
|
+
sunspot_matchers_testunit!
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011 Joseph Palermo, Pivotal Labs, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE
|
data/README.markdown
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
# Sunspot Matchers
|
2
|
+
|
3
|
+
[Sunspot](http://outoftime.github.com/sunspot/) is a great Ruby library for constructing searches against Solr. However,
|
4
|
+
because of the way the Sunspot DSL is constructed, it can be difficult to do simple assertions about your searches
|
5
|
+
without doing full integration tests.
|
6
|
+
|
7
|
+
The goal of these matchers are to make it easier to unit test search logic without having to construct the individual
|
8
|
+
fixture scenarios inside of Solr and then actually perform a search against Solr.
|
9
|
+
|
10
|
+
This is a direct port of the excellent [Sunspot Matchers](http://github.com/pivotal/sunspot_matchers) library by Joseph
|
11
|
+
Palermo, rewritten for use with Test::Unit.
|
12
|
+
|
13
|
+
# Installation
|
14
|
+
|
15
|
+
You will need to replace the Sunspot Session object with the spy provided. You can do this globally by putting the
|
16
|
+
following in a setup block or your test_helper.
|
17
|
+
|
18
|
+
def setup
|
19
|
+
Sunspot.session = SunspotMatchers::SunspotSessionSpy.new(Sunspot.session)
|
20
|
+
end
|
21
|
+
|
22
|
+
Keep in mind, this will prevent any test from actually hitting Solr, so if you have integration tests, you'll either
|
23
|
+
need to be more careful which tests you replace the session for, or you'll need to restore the original session before
|
24
|
+
those tests
|
25
|
+
|
26
|
+
Sunspot.session = Sunspot.session.original_session
|
27
|
+
|
28
|
+
You will also need to include the matchers in your tests. Again, this can be done globally in your test_helper.
|
29
|
+
|
30
|
+
require 'sunspot_matchers_testunit'
|
31
|
+
include SunspotMatchersTestunit
|
32
|
+
|
33
|
+
Alternately, you could include them into individual tests if needed.
|
34
|
+
|
35
|
+
# Matchers
|
36
|
+
|
37
|
+
## assert_is_search_for
|
38
|
+
|
39
|
+
If you perform a search against your Post model, you could write this assertion:
|
40
|
+
|
41
|
+
`assert_is_search_for Sunspot.session, Post`
|
42
|
+
|
43
|
+
Individual searches are stored in an array, so if you perform multiple, you'll have to match against them manually. Without
|
44
|
+
an explicit search specified, it will use the last one.
|
45
|
+
|
46
|
+
`assert_is_search_for Sunspot.session.searches.first, Post`
|
47
|
+
|
48
|
+
## assert_has_search_params
|
49
|
+
|
50
|
+
This is where the bulk of the functionality lies. There are seven types of search matches you can perform: `keywords`,
|
51
|
+
`with`, `without`, `paginate`, `order_by`, `facet`, and `boost`.
|
52
|
+
|
53
|
+
In all of the examples below, the arguments fully match the search terms. This is not expected or required. You can
|
54
|
+
have a dozen `with` restrictions on a search and still write an expectation on a single one of them.
|
55
|
+
|
56
|
+
Negative expectations also work correctly. `assert_has_no_search_params` will fail if the search actually includes the
|
57
|
+
provided arguments.
|
58
|
+
|
59
|
+
With all matchers, you can specify a `Proc` as the second argument, and perform multi statement expectations inside the
|
60
|
+
Proc. Keep in mind, that only the search type specified in the first argument will actually be checked. So if you specify
|
61
|
+
`keywords` and `with` restrictions in the same Proc, but you said `assert_has_search_params Sunspot.session, :keywords, ...`
|
62
|
+
the `with` restrictions are simply ignored.
|
63
|
+
|
64
|
+
### wildcard matching
|
65
|
+
|
66
|
+
keywords, with, without, and order_by support wildcard expectations using the `any_param` parameter:
|
67
|
+
|
68
|
+
Sunspot.search(Post) do
|
69
|
+
with :blog_id, 4
|
70
|
+
order_by :blog_id, :desc
|
71
|
+
end
|
72
|
+
|
73
|
+
assert_has_search_params Sunspot.session, [ :with, :blog_id, any_param ]
|
74
|
+
assert_has_search_params Sunspot.session, [ :order_by, :blog_id, any_param ]
|
75
|
+
assert_has_search_params Sunspot.session, [ :order_by, any_param ]
|
76
|
+
assert_has_no_search_params Sunspot.session, [ :order_by, :category_ids, any_param ]
|
77
|
+
|
78
|
+
### :keywords
|
79
|
+
|
80
|
+
You can match against a keyword search:
|
81
|
+
|
82
|
+
Sunspot.search(Post) do
|
83
|
+
keywords 'great pizza'
|
84
|
+
end
|
85
|
+
|
86
|
+
assert_has_search_params Sunspot.session, [ :keywords, 'great pizza' ]
|
87
|
+
|
88
|
+
### :with
|
89
|
+
|
90
|
+
You can match against a with restriction:
|
91
|
+
|
92
|
+
Sunspot.search(Post) do
|
93
|
+
with :author_name, 'Mark Twain'
|
94
|
+
end
|
95
|
+
|
96
|
+
assert_has_search_params Sunspot.session, [ :with, :author_name, 'Mark Twain' ]
|
97
|
+
|
98
|
+
Complex conditions can be matched by using a Proc instead of a value. Be aware that order does matter, not for
|
99
|
+
the actual results that would come out of Solr, but the matcher will fail of the order of `with` restrictions is
|
100
|
+
different.
|
101
|
+
|
102
|
+
Sunspot.search(Post) do
|
103
|
+
any_of do
|
104
|
+
with :category_ids, 1
|
105
|
+
with :category_ids, 2
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
assert_has_search_params Sunspot.session, [ :with, Proc.new {
|
110
|
+
any_of do
|
111
|
+
with :category_ids, 1
|
112
|
+
with :category_ids, 2
|
113
|
+
end
|
114
|
+
} ]
|
115
|
+
|
116
|
+
### :without
|
117
|
+
|
118
|
+
Without is nearly identical to with:
|
119
|
+
|
120
|
+
Sunspot.search(Post) do
|
121
|
+
without :author_name, 'Mark Twain'
|
122
|
+
end
|
123
|
+
|
124
|
+
assert_has_search_params Sunspot.session, [ :without, :author_name, 'Mark Twain' ]
|
125
|
+
|
126
|
+
### :paginate
|
127
|
+
|
128
|
+
You can also specify only page or per_page, both are not required.
|
129
|
+
|
130
|
+
Sunspot.search(Post) do
|
131
|
+
paginate :page => 3, :per_page => 15
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_has_search_params Sunspot.session, [ :paginate, :page => 3, :per_page => 15 ]
|
135
|
+
|
136
|
+
### :order_by
|
137
|
+
|
138
|
+
Expectations on multiple orderings are supported using using the Proc format mentioned above.
|
139
|
+
|
140
|
+
Sunspot.search(Post) do
|
141
|
+
order_by :published_at, :desc
|
142
|
+
end
|
143
|
+
|
144
|
+
assert_has_search_params Sunspot.session, [ :order_by, :published_at, :desc ]
|
145
|
+
|
146
|
+
### :facet
|
147
|
+
|
148
|
+
Standard faceting expectation:
|
149
|
+
|
150
|
+
Sunspot.search(Post) do
|
151
|
+
facet :category_ids
|
152
|
+
end
|
153
|
+
|
154
|
+
assert_has_search_params Sunspot.session, [ :facet, :category_ids ]
|
155
|
+
|
156
|
+
Faceting where a query is excluded:
|
157
|
+
|
158
|
+
Sunspot.search(Post) do
|
159
|
+
category_filter = with(:category_ids, 2)
|
160
|
+
facet(:category_ids, :exclude => category_filter)
|
161
|
+
end
|
162
|
+
|
163
|
+
assert_has_search_params Sunspot.session, [ :facet, Proc.new {
|
164
|
+
category_filter = with(:category_ids, 2)
|
165
|
+
facet(:category_ids, :exclude => category_filter)
|
166
|
+
} ]
|
167
|
+
|
168
|
+
Query faceting:
|
169
|
+
|
170
|
+
Sunspot.search(Post) do
|
171
|
+
facet(:average_rating) do
|
172
|
+
row(1.0..2.0) do
|
173
|
+
with(:average_rating, 1.0..2.0)
|
174
|
+
end
|
175
|
+
row(2.0..3.0) do
|
176
|
+
with(:average_rating, 2.0..3.0)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
assert_has_search_params Sunspot.session, [ :facet, Proc.new {
|
182
|
+
facet(:average_rating) do
|
183
|
+
row(1.0..2.0) do
|
184
|
+
with(:average_rating, 1.0..2.0)
|
185
|
+
end
|
186
|
+
row(2.0..3.0) do
|
187
|
+
with(:average_rating, 2.0..3.0)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
} ]
|
191
|
+
|
192
|
+
### :boost
|
193
|
+
|
194
|
+
Field boost matching:
|
195
|
+
|
196
|
+
Sunspot.search(Post) do
|
197
|
+
keywords 'great pizza' do
|
198
|
+
boost_fields :body => 2.0
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
assert_has_search_params Sunspot.session, [ :boost, Proc.new {
|
203
|
+
keywords 'great pizza' do
|
204
|
+
boost_fields :body => 2.0
|
205
|
+
end
|
206
|
+
} ]
|
207
|
+
|
208
|
+
Boost query matching:
|
209
|
+
|
210
|
+
Sunspot.search(Post) do
|
211
|
+
keywords 'great pizza' do
|
212
|
+
boost(2.0) do
|
213
|
+
with :blog_id, 4
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
assert_has_search_params Sunspot.session, [ :boost, Proc.new {
|
219
|
+
keywords 'great pizza' do
|
220
|
+
boost(2.0) do
|
221
|
+
with :blog_id, 4
|
222
|
+
end
|
223
|
+
end
|
224
|
+
} ]
|
225
|
+
|
226
|
+
Boost function matching:
|
227
|
+
|
228
|
+
Sunspot.search(Post) do
|
229
|
+
keywords 'great pizza' do
|
230
|
+
boost(function { sum(:average_rating, product(:popularity, 10)) })
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
assert_has_search_params Sunspot.session, [ :boost, Proc.new {
|
235
|
+
keywords 'great pizza' do
|
236
|
+
boost(function { sum(:average_rating, product(:popularity, 10)) })
|
237
|
+
end
|
238
|
+
} ]
|
data/Rakefile
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'test/unit/assertions'
|
2
|
+
|
3
|
+
module SunspotMatchersTestunit
|
4
|
+
class BaseMatcher
|
5
|
+
attr_accessor :args
|
6
|
+
|
7
|
+
def initialize(session, args)
|
8
|
+
@session = session
|
9
|
+
@args = args
|
10
|
+
build_comparison_search
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_comparison_search
|
14
|
+
@comparison_search = if(@args.last.is_a?(Proc))
|
15
|
+
SunspotMatchersTestunit::SunspotSessionSpy.new(@session).build_search(search_types, &args.last)
|
16
|
+
else
|
17
|
+
SunspotMatchersTestunit::SunspotSessionSpy.new(@session).build_search(search_types) do
|
18
|
+
send(search_method, *args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def search_tuple
|
24
|
+
search_tuple = @session.is_a?(Array) ? @session : @session.searches.last
|
25
|
+
raise 'no search found' unless search_tuple
|
26
|
+
search_tuple
|
27
|
+
end
|
28
|
+
|
29
|
+
def actual_search
|
30
|
+
search_tuple.last
|
31
|
+
end
|
32
|
+
|
33
|
+
def search_types
|
34
|
+
search_tuple.first
|
35
|
+
end
|
36
|
+
|
37
|
+
def wildcard?
|
38
|
+
@args && @args.last == any_param
|
39
|
+
end
|
40
|
+
|
41
|
+
def field
|
42
|
+
@args && @args.first
|
43
|
+
end
|
44
|
+
|
45
|
+
def query_params_for_search(search)
|
46
|
+
search.instance_variable_get(:@query).to_params
|
47
|
+
end
|
48
|
+
|
49
|
+
def actual_params
|
50
|
+
@actual_params ||= query_params_for_search(actual_search)
|
51
|
+
end
|
52
|
+
|
53
|
+
def comparison_params
|
54
|
+
@comparison_params ||= query_params_for_search(@comparison_search)
|
55
|
+
end
|
56
|
+
|
57
|
+
def match?
|
58
|
+
differences.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
def missing_param_error_message
|
62
|
+
missing_params = differences
|
63
|
+
actual_values = missing_params.keys.collect {|key| "#{key} => #{actual_params[key]}"}
|
64
|
+
missing_values = missing_params.collect{ |key, value| "#{key} => #{value}"}
|
65
|
+
"expected search params: #{actual_values.join(' and ')} to match expected: #{missing_values.join(' and ')}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def unexpected_match_error_message
|
69
|
+
actual_values = keys_to_compare.collect {|key| "#{key} => #{actual_params[key]}"}
|
70
|
+
comparison_values = keys_to_compare.collect {|key| "#{key} => #{comparison_params[key]}"}
|
71
|
+
"expected search params: #{actual_values.join(' and ')} NOT to match expected: #{comparison_values.join(' and ')}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def differences
|
75
|
+
keys_to_compare.inject({}) do |hsh, key|
|
76
|
+
result = compare_key(key)
|
77
|
+
hsh[key] = result unless result.empty?
|
78
|
+
hsh
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def compare_key(key)
|
83
|
+
if(actual_params[key].is_a?(Array) || comparison_params[key].is_a?(Array))
|
84
|
+
compare_multi_value(actual_params[key], comparison_params[key])
|
85
|
+
else
|
86
|
+
compare_single_value(actual_params[key], comparison_matcher_for_key(key))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def comparison_matcher_for_key(key)
|
91
|
+
if wildcard? && wildcard_matcher_for_keys.has_key?(key)
|
92
|
+
wildcard_matcher_for_keys[key]
|
93
|
+
else
|
94
|
+
comparison_params[key]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def compare_single_value(actual, comparison)
|
99
|
+
if comparison.is_a?(Regexp)
|
100
|
+
return [] if comparison =~ actual
|
101
|
+
return [comparison.source]
|
102
|
+
end
|
103
|
+
return [comparison] unless actual == comparison
|
104
|
+
[]
|
105
|
+
end
|
106
|
+
|
107
|
+
def compare_multi_value(actual, comparison)
|
108
|
+
filter_values(comparison).reject do |value|
|
109
|
+
next false unless actual
|
110
|
+
value_matcher = Regexp.new(Regexp.escape(value))
|
111
|
+
actual.any?{ |actual_value| actual_value =~ value_matcher }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def filter_values(values)
|
116
|
+
return values unless wildcard?
|
117
|
+
field_matcher = Regexp.new(field.to_s)
|
118
|
+
values.select{ |value| field_matcher =~ value }.collect{|value| value.gsub(/:.*/, '')}
|
119
|
+
end
|
120
|
+
|
121
|
+
def wildcard_matcher_for_keys
|
122
|
+
{}
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class HaveSearchParams
|
127
|
+
include Test::Unit::Assertions
|
128
|
+
|
129
|
+
def initialize(session, method, *args)
|
130
|
+
@session = session
|
131
|
+
@method = method
|
132
|
+
@args = args
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_matcher
|
136
|
+
matcher_class = case @method
|
137
|
+
when :with
|
138
|
+
WithMatcher
|
139
|
+
when :without
|
140
|
+
WithoutMatcher
|
141
|
+
when :keywords
|
142
|
+
KeywordsMatcher
|
143
|
+
when :boost
|
144
|
+
BoostMatcher
|
145
|
+
when :facet
|
146
|
+
FacetMatcher
|
147
|
+
when :order_by
|
148
|
+
OrderByMatcher
|
149
|
+
when :paginate
|
150
|
+
PaginationMatcher
|
151
|
+
end
|
152
|
+
matcher_class.new(@session, @args)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def assert_has_search_params(session, method_and_args)
|
157
|
+
method, *args = method_and_args
|
158
|
+
matcher = HaveSearchParams.new(session, method, *args).get_matcher
|
159
|
+
assert matcher.match?, matcher.missing_param_error_message
|
160
|
+
end
|
161
|
+
|
162
|
+
def assert_has_no_search_params(session, method_and_args)
|
163
|
+
method, *args = method_and_args
|
164
|
+
matcher = HaveSearchParams.new(session, method, *args).get_matcher
|
165
|
+
assert !matcher.match?, matcher.unexpected_match_error_message
|
166
|
+
end
|
167
|
+
|
168
|
+
class WithMatcher < BaseMatcher
|
169
|
+
def search_method
|
170
|
+
:with
|
171
|
+
end
|
172
|
+
|
173
|
+
def keys_to_compare
|
174
|
+
[:fq]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class WithoutMatcher < BaseMatcher
|
179
|
+
def search_method
|
180
|
+
:without
|
181
|
+
end
|
182
|
+
|
183
|
+
def keys_to_compare
|
184
|
+
[:fq]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class KeywordsMatcher < BaseMatcher
|
189
|
+
def search_method
|
190
|
+
:keywords
|
191
|
+
end
|
192
|
+
|
193
|
+
def keys_to_compare
|
194
|
+
[:q, :qf]
|
195
|
+
end
|
196
|
+
|
197
|
+
def wildcard_matcher_for_keys
|
198
|
+
{:q => /./, :qf => /./}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class BoostMatcher < BaseMatcher
|
203
|
+
def search_method
|
204
|
+
:boost
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
def keys_to_compare
|
209
|
+
[:qf, :bq, :bf]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class FacetMatcher < BaseMatcher
|
214
|
+
def search_method
|
215
|
+
:facet
|
216
|
+
end
|
217
|
+
|
218
|
+
def keys_to_compare
|
219
|
+
comparison_params.keys.select {|key| /facet/ =~ key.to_s}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class OrderByMatcher < BaseMatcher
|
224
|
+
def search_method
|
225
|
+
:order_by
|
226
|
+
end
|
227
|
+
|
228
|
+
def keys_to_compare
|
229
|
+
[:sort]
|
230
|
+
end
|
231
|
+
|
232
|
+
def wildcard_matcher_for_keys
|
233
|
+
return {:sort => /./} if field_wildcard?
|
234
|
+
param = comparison_params[:sort]
|
235
|
+
regex = Regexp.new(param.gsub(any_param, '.*'))
|
236
|
+
{:sort => regex}
|
237
|
+
end
|
238
|
+
|
239
|
+
def field_wildcard?
|
240
|
+
@args.first == any_param
|
241
|
+
end
|
242
|
+
|
243
|
+
def direction_wildcard?
|
244
|
+
@args.length == 2 && @args.last == any_param
|
245
|
+
end
|
246
|
+
|
247
|
+
def args
|
248
|
+
return @args unless direction_wildcard?
|
249
|
+
@args[0...-1] + [:asc]
|
250
|
+
end
|
251
|
+
|
252
|
+
def build_comparison_search
|
253
|
+
if field_wildcard?
|
254
|
+
@comparison_params = {:sort => any_param}
|
255
|
+
elsif direction_wildcard?
|
256
|
+
super
|
257
|
+
@comparison_params = comparison_params
|
258
|
+
@comparison_params[:sort].gsub!("asc", any_param)
|
259
|
+
else
|
260
|
+
super
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
class PaginationMatcher < BaseMatcher
|
266
|
+
def search_method
|
267
|
+
:paginate
|
268
|
+
end
|
269
|
+
|
270
|
+
def keys_to_compare
|
271
|
+
[:rows, :start]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
class BeASearchFor
|
276
|
+
def initialize(session, expected_class)
|
277
|
+
@session = session
|
278
|
+
@expected_class = expected_class
|
279
|
+
end
|
280
|
+
|
281
|
+
def match?
|
282
|
+
search_types.include?(@expected_class)
|
283
|
+
end
|
284
|
+
|
285
|
+
def search_tuple
|
286
|
+
search_tuple = @session.is_a?(Array) ? @session : @session.searches.last
|
287
|
+
raise 'no search found' unless search_tuple
|
288
|
+
search_tuple
|
289
|
+
end
|
290
|
+
|
291
|
+
def search_types
|
292
|
+
search_tuple.first
|
293
|
+
end
|
294
|
+
|
295
|
+
def failure_message_for_should
|
296
|
+
"expected search class: #{search_types.join(' and ')} to match expected class: #{@expected_class}"
|
297
|
+
end
|
298
|
+
|
299
|
+
def failure_message_for_should_not
|
300
|
+
"expected search class: #{search_types.join(' and ')} NOT to match expected class: #{@expected_class}"
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def assert_is_search_for(session, expected_class)
|
305
|
+
matcher = BeASearchFor.new(session, expected_class)
|
306
|
+
assert matcher.match?, matcher.failure_message_for_should
|
307
|
+
end
|
308
|
+
|
309
|
+
def assert_is_not_search_for(session, expected_class)
|
310
|
+
matcher = BeASearchFor.new(session, expected_class)
|
311
|
+
assert !matcher.match?, matcher.failure_message_for_should_not
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def any_param
|
316
|
+
"ANY_PARAM"
|
317
|
+
end
|