rspec-solr 0.1.0 → 0.1.2
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/.yardopts +3 -0
- data/{expectation_matchers.rdoc → MATCHERS.rdoc} +8 -6
- data/README.rdoc +118 -3
- data/lib/rspec-solr/solr_response_hash.rb +7 -1
- data/lib/rspec-solr/version.rb +1 -1
- data/lib/tasks/doc.rake +1 -1
- data/rspec-solr.gemspec +1 -1
- data/spec/include_document_spec.rb +41 -7
- metadata +7 -6
data/.yardopts
ADDED
@@ -44,25 +44,26 @@
|
|
44
44
|
To change the id field name, use my_solr_response_hash.id_field='my_id_fldname'
|
45
45
|
===== Hash
|
46
46
|
* ("fldname" => "value")
|
47
|
-
* ("
|
48
|
-
|
49
|
-
|
47
|
+
* ("fldname" => /regex_to_match_val/)
|
48
|
+
* ("fld1" => "val1", "fld2" => /val2_regex/)
|
49
|
+
NOTE: single Solr document must satisfy all key value pairs
|
50
|
+
* ("fldname" => ["val1", /val2_regex/, "val3"])
|
50
51
|
NOTE: all of the Array values must be present for the fld in a single Solr document
|
51
52
|
should_not for Array implies NONE of the values should be present in a single document
|
52
53
|
TODO:
|
53
|
-
* document("fldname" => "/regex/")
|
54
54
|
* include_title("val") (i.e. include_anyFieldName("val") )
|
55
55
|
|
56
56
|
==== Specifying Multiple Documents
|
57
57
|
===== Array
|
58
58
|
* by id strings: (["id1", "id2", "id3"])
|
59
|
-
* by hashes: ([{"title" => "green is best"}, {"title" =>
|
59
|
+
* by hashes: ([{"title" => "green is best"}, {"title" => /blue/}, {"fld" => "val"}])
|
60
60
|
NOTE: you cannot do this: ([{"title" => ["Solr doc 1 title", "Solr doc 2 title"]} ]) to specify multiple documents
|
61
61
|
* by mix of id strings and hashes: ([{"title" => "green is best"}, "id3", {"author" => "steinbeck"}])
|
62
62
|
|
63
63
|
==== Full Examples
|
64
64
|
* rspec-solr_resp_hash.should include("fld1" => "val1")
|
65
|
-
* rspec-solr_resp_hash.should include("
|
65
|
+
* rspec-solr_resp_hash.should include("fld1" => /regex_for_val/)
|
66
|
+
* rspec-solr_resp_hash.should include("f1" => "v1", "f2" => ["val1", "val2", /regex_for_val/])
|
66
67
|
* rspec-solr_resp_hash.should include("idval")
|
67
68
|
* rspec-solr_resp_hash.should include(["id1", "id2", "id3"])
|
68
69
|
* rspec-solr_resp_hash.should include([{"title" => "title1"}, {"title" => "title2"}])
|
@@ -85,6 +86,7 @@ TODO:
|
|
85
86
|
|
86
87
|
TODO:
|
87
88
|
* include_at_least(3).of_these_documents().in_first(3).results
|
89
|
+
* start_with()
|
88
90
|
|
89
91
|
=== Usage
|
90
92
|
See above for information on how to specify specific documents
|
data/README.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
{<img src="https://secure.travis-ci.org/sul-dlss/rspec-solr.png?branch=master" alt="Build Status" />}[http://travis-ci.org/sul-dlss/rspec-solr]
|
4
4
|
|
5
|
-
|
5
|
+
A Gem to provide RSpec custom matchers to be used with Solr response objects.
|
6
6
|
|
7
7
|
== Installation
|
8
8
|
|
@@ -20,11 +20,122 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
== Usage
|
22
22
|
|
23
|
-
See
|
23
|
+
See MATCHERS.rdoc for syntax of supported expectations.
|
24
|
+
|
25
|
+
=== Examples:
|
26
|
+
|
27
|
+
it "q of 'Buddhism' should get 8,500-10,500 results" do
|
28
|
+
resp = solr_resp_doc_ids_only({'q'=>'Buddhism'})
|
29
|
+
resp.should have_at_least(8500).documents
|
30
|
+
resp.should have_at_most(10500).documents
|
31
|
+
end
|
32
|
+
|
33
|
+
it "q of 'Two3' should have excellent results", :jira => 'VUF-386' do
|
34
|
+
resp = solr_resp_doc_ids_only({'q'=>'Two3'})
|
35
|
+
resp.should have_at_most(10).documents
|
36
|
+
resp.should include("5732752").as_first_result
|
37
|
+
resp.should include("8564713").in_first(2).results
|
38
|
+
resp.should_not include("5727394")
|
39
|
+
resp.should have_the_same_number_of_results_as(solr_resp_doc_ids_only({'q'=>'two3'}))
|
40
|
+
resp.should have_fewer_results_than(solr_resp_doc_ids_only({'q'=>'two 3'}))
|
41
|
+
end
|
42
|
+
|
43
|
+
it "Traditional Chinese chars 三國誌 should get the same results as simplified chars 三国志" do
|
44
|
+
resp = solr_resp_doc_ids_only({'q'=>'三國誌'})
|
45
|
+
resp.should have_at_least(240).documents
|
46
|
+
resp.should have_the_same_number_of_results_as(solr_resp_doc_ids_only({'q'=>'三国志'}))
|
47
|
+
end
|
48
|
+
|
49
|
+
=== How Do I Do That?
|
50
|
+
|
51
|
+
Essentially, you write a bunch of specs that
|
52
|
+
* send a request to your Solr index
|
53
|
+
* wrap the Solr Ruby response into the RSpecSolr::SolrResponseHash (blah = RSpecSolr::SolrResponseHash.new(orig_resp))
|
54
|
+
* utilize the matchers (blah.should have_document("222")) -- see MATCHERS.rdoc
|
55
|
+
|
56
|
+
There is an exemplar project utilizing rspec-solr at https://github.com/sul-dlss/sw_index_tests.
|
57
|
+
|
58
|
+
Besides the specs themselves, it has essentially 4 files to smooth the way.
|
59
|
+
|
60
|
+
==== 1. Gemfile
|
61
|
+
Indicate the required gems for bundler
|
62
|
+
|
63
|
+
source :rubygems
|
64
|
+
|
65
|
+
gem 'RedCloth' # for textile formatting used in Readme
|
66
|
+
gem 'rake'
|
67
|
+
gem 'rsolr' # for sending requests to and getting responses from solr
|
68
|
+
gem 'rspec-solr' # for rspec assertions against solr response object
|
69
|
+
|
70
|
+
==== 2. Rakefile
|
71
|
+
Make it easy to run various groups of specs from the command line
|
72
|
+
|
73
|
+
require 'rspec/core/rake_task'
|
74
|
+
|
75
|
+
desc "run specs expected to pass"
|
76
|
+
RSpec::Core::RakeTask.new(:rspec) do |spec|
|
77
|
+
spec.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
|
78
|
+
end
|
79
|
+
|
80
|
+
==== 3. config/solr.yml
|
81
|
+
Your Solr base url goes here
|
82
|
+
|
83
|
+
test:
|
84
|
+
:url: http://your_solr_baseurl
|
85
|
+
|
86
|
+
dev:
|
87
|
+
:url: http://your_solr_baseurl
|
88
|
+
|
89
|
+
==== 4. spec/spec_helper.rb
|
90
|
+
Do a one time setup of Solr connection, and methods to make it easier to make desired Solr requests
|
91
|
+
|
92
|
+
require "yaml"
|
93
|
+
require 'rsolr'
|
94
|
+
|
95
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
96
|
+
|
97
|
+
RSpec.configure do |config|
|
98
|
+
# FIXME: hardcoded yml group
|
99
|
+
solr_config = YAML::load_file('config/solr.yml')["test"]
|
100
|
+
@@solr = RSolr.connect(solr_config)
|
101
|
+
puts "Solr URL: #{@@solr.uri}"
|
102
|
+
end
|
103
|
+
|
104
|
+
# send a GET request to the default Solr request handler with the indicated Solr parameters
|
105
|
+
# @param solr_params [Hash] the key/value pairs to be sent to Solr as HTTP parameters, in addition to
|
106
|
+
# those to get only id fields and no facets in the response
|
107
|
+
# @return [RSpecSolr::SolrResponseHash] object for rspec-solr testing the Solr response
|
108
|
+
def solr_resp_doc_ids_only(solr_params)
|
109
|
+
solr_response(solr_params.merge(@@doc_ids_only))
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# send a GET request to the indicated Solr request handler with the indicated Solr parameters
|
115
|
+
# @param solr_params [Hash] the key/value pairs to be sent to Solr as HTTP parameters
|
116
|
+
# @param req_handler [String] the pathname of the desired Solr request handler (defaults to 'select')
|
117
|
+
# @return [RSpecSolr::SolrResponseHash] object for rspec-solr testing the Solr response
|
118
|
+
def solr_response(solr_params, req_handler='select')
|
119
|
+
RSpecSolr::SolrResponseHash.new(@@solr.send_and_receive(req_handler, {:method => :get, :params => solr_params}))
|
120
|
+
end
|
121
|
+
|
122
|
+
# use these Solr HTTP params to reduce the size of the Solr responses
|
123
|
+
# response documents will only have id fields, and there will be no facets in the response
|
124
|
+
# @return [Hash] Solr HTTP params to reduce the size of the Solr responses
|
125
|
+
def doc_ids_only
|
126
|
+
{'fl'=>'id', 'facet'=>'false'}
|
127
|
+
end
|
128
|
+
|
24
129
|
|
25
130
|
== Ruby Version Compatibility
|
26
131
|
|
27
|
-
This should work with various rubies 1.8.7, but currently some tests expected ordered hashes (though the code itself doesn't require them).
|
132
|
+
This should work with various rubies 1.8.7, but currently some tests expected ordered hashes (though the code itself doesn't require them - just THIS gem's TEST code).
|
133
|
+
|
134
|
+
== Contribute
|
135
|
+
|
136
|
+
I'm currently envisioning helper methods shared somehow - either on the github wikis, or in this gem as exemplars, or in a separate gem, or ...
|
137
|
+
|
138
|
+
Please share yours!
|
28
139
|
|
29
140
|
== Contributing
|
30
141
|
|
@@ -33,3 +144,7 @@ This should work with various rubies 1.8.7, but currently some tests expected or
|
|
33
144
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
34
145
|
4. Push to the branch (`git push origin my-new-feature`)
|
35
146
|
5. Create new Pull Request
|
147
|
+
|
148
|
+
== Releases
|
149
|
+
- in progress ... 0.1.1 improve README
|
150
|
+
- <b>0.1.0</b> Initial release
|
@@ -36,6 +36,7 @@ class RSpecSolr
|
|
36
36
|
# @example expected_doc Array
|
37
37
|
# ["1", "2", "3"] implies we expect Solr docs with ids 1, 2, 3 included in this response
|
38
38
|
# [{"title" => "warm fuzzies"}, {"title" => "cool fuzzies"}] implies we expect at least one Solr doc in this response matching each Hash in the Array
|
39
|
+
# [{"title" => /rm fuzz/}, {"title" => /^cool/}] implies we expect at least one Solr doc in this response matching each Hash in the Array
|
39
40
|
# @param [FixNum] max_doc_position maximum acceptable position (1-based) of document in results. (e.g. if 2, it must be the 1st or 2nd doc in the results)
|
40
41
|
def has_document?(expected_doc, max_doc_position = nil)
|
41
42
|
if expected_doc.is_a?(Hash)
|
@@ -47,7 +48,12 @@ class RSpecSolr
|
|
47
48
|
# if it's an Array, then all expected values must be present
|
48
49
|
Array(exp_vals).all? { | exp_val |
|
49
50
|
# a doc's fld values can be a String or an Array
|
50
|
-
|
51
|
+
case exp_val
|
52
|
+
when Regexp
|
53
|
+
Array(doc[exp_fname]).any? { |val| val =~ exp_val }
|
54
|
+
else
|
55
|
+
Array(doc[exp_fname]).include?(exp_val)
|
56
|
+
end
|
51
57
|
} &&
|
52
58
|
# satisfy doc's position in the results
|
53
59
|
(max_doc_position ? docs.find_index(doc) < max_doc_position : true)
|
data/lib/rspec-solr/version.rb
CHANGED
data/lib/tasks/doc.rake
CHANGED
@@ -11,7 +11,7 @@ begin
|
|
11
11
|
yt.options = ['--output-dir', doc_dest_dir,
|
12
12
|
'--readme', 'README.rdoc',
|
13
13
|
'--title', 'RSpec-Solr Documentation',
|
14
|
-
'--files', '
|
14
|
+
'--files', 'MATCHERS.rdoc']
|
15
15
|
end
|
16
16
|
rescue LoadError
|
17
17
|
desc "Generate YARD Documentation"
|
data/rspec-solr.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.summary = "RSpec custom matchers for Solr response objects"
|
12
12
|
gem.homepage = "http://github.com/sul-dlss/rspec-solr"
|
13
13
|
|
14
|
-
gem.extra_rdoc_files = ["LICENSE.txt", "README.rdoc", "
|
14
|
+
gem.extra_rdoc_files = ["LICENSE.txt", "README.rdoc", "MATCHERS.rdoc"]
|
15
15
|
gem.files = `git ls-files`.split($\)
|
16
16
|
gem.test_files = gem.files.grep(%r{^spec/})
|
17
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -93,8 +93,7 @@ describe RSpecSolr do
|
|
93
93
|
it "passes if no part of the expectatio is met" do
|
94
94
|
@solr_resp_5_docs.should_not include("id" => "not_there", "not_there" => "anything")
|
95
95
|
end
|
96
|
-
end # should_not include('fld1'=>'val1', 'fld2'=>'val2')
|
97
|
-
|
96
|
+
end # should_not include('fld1'=>'val1', 'fld2'=>'val2')
|
98
97
|
|
99
98
|
context "multi-valued fields and expectations" do
|
100
99
|
|
@@ -285,7 +284,7 @@ describe RSpecSolr do
|
|
285
284
|
|
286
285
|
context "should include(Array_of_Hashes)" do
|
287
286
|
it "passes if all Hashes in Array match all Solr documents in the response" do
|
288
|
-
@solr_resp_5_docs.should include([{"id"=>"111", "fld"
|
287
|
+
@solr_resp_5_docs.should include([{"id"=>"111", "fld"=>/val/, "fld2"=>"val2"},
|
289
288
|
{"id"=>"222"},
|
290
289
|
{"id"=>"333", "fld"=>"val"},
|
291
290
|
{"id"=>"444", "fld"=>["val1", "val2", "val3"]},
|
@@ -361,11 +360,46 @@ describe RSpecSolr do
|
|
361
360
|
|
362
361
|
context "regex value" do
|
363
362
|
|
364
|
-
context
|
365
|
-
it "
|
366
|
-
|
363
|
+
context "should include('fld' => /regex/)" do
|
364
|
+
it "passes if Solr document in response matches regex in named field" do
|
365
|
+
@solr_resp_5_docs.should include("id" => /\d{3}/)
|
366
|
+
@solr_resp_5_docs.should include("fld" => /^va/) # 2 docs match
|
367
367
|
end
|
368
|
-
|
368
|
+
it "passes if single value expectation is expressed as an Array" do
|
369
|
+
@solr_resp_5_docs.should include("id" => [/111/])
|
370
|
+
end
|
371
|
+
it "fails if no Solr document in response has 'fldval' for the named field" do
|
372
|
+
lambda {
|
373
|
+
@solr_resp_5_docs.should include("id" => /not there/)
|
374
|
+
}.should fail_matching('} to include {"id"=>/not there/}')
|
375
|
+
end
|
376
|
+
it "fails if no Solr document in response has the named field" do
|
377
|
+
lambda {
|
378
|
+
@solr_resp_5_docs.should include("not_there" => /anything/)
|
379
|
+
}.should fail_matching('} to include {"not_there"=>/anything/}')
|
380
|
+
end
|
381
|
+
end # should include('fld' => /regex/)
|
382
|
+
|
383
|
+
context "should_NOT include('fld' => /regex/)" do
|
384
|
+
it "fails if Solr document in response matches regex in named field" do
|
385
|
+
lambda {
|
386
|
+
@solr_resp_5_docs.should_not include("id" => /\d{3}/)
|
387
|
+
}.should fail_matching('not to include {"id"=>/\d{3}/}')
|
388
|
+
lambda {
|
389
|
+
@solr_resp_5_docs.should_not include("fld" => /^va/)
|
390
|
+
}.should fail_matching('not to include {"fld"=>/^va/}')
|
391
|
+
end
|
392
|
+
it "passes if no Solr document in response has 'fldval' for the named field" do
|
393
|
+
@solr_resp_5_docs.should_not include({"id" => /not there/})
|
394
|
+
end
|
395
|
+
it "passes if no Solr document in response has the named field" do
|
396
|
+
@solr_resp_5_docs.should_not include({"not_there" => /anything/})
|
397
|
+
end
|
398
|
+
it "passes if single field value is expressed as Array" do
|
399
|
+
@solr_resp_5_docs.should_not include({"id" => [/not there/]})
|
400
|
+
end
|
401
|
+
|
402
|
+
end # should_NOT include('fld' => /regex/)
|
369
403
|
|
370
404
|
end # regex value
|
371
405
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-solr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-10-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -133,16 +133,17 @@ extensions: []
|
|
133
133
|
extra_rdoc_files:
|
134
134
|
- LICENSE.txt
|
135
135
|
- README.rdoc
|
136
|
-
-
|
136
|
+
- MATCHERS.rdoc
|
137
137
|
files:
|
138
138
|
- .gitignore
|
139
139
|
- .rvmrc
|
140
140
|
- .travis.yml
|
141
|
+
- .yardopts
|
141
142
|
- Gemfile
|
142
143
|
- LICENSE.txt
|
144
|
+
- MATCHERS.rdoc
|
143
145
|
- README.rdoc
|
144
146
|
- Rakefile
|
145
|
-
- expectation_matchers.rdoc
|
146
147
|
- lib/rspec-solr.rb
|
147
148
|
- lib/rspec-solr/compare_num_docs_matcher.rb
|
148
149
|
- lib/rspec-solr/have_documents_matcher.rb
|
@@ -176,7 +177,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
176
177
|
version: '0'
|
177
178
|
segments:
|
178
179
|
- 0
|
179
|
-
hash:
|
180
|
+
hash: -4597988063406856522
|
180
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
182
|
none: false
|
182
183
|
requirements:
|
@@ -185,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
186
|
version: '0'
|
186
187
|
segments:
|
187
188
|
- 0
|
188
|
-
hash:
|
189
|
+
hash: -4597988063406856522
|
189
190
|
requirements: []
|
190
191
|
rubyforge_project:
|
191
192
|
rubygems_version: 1.8.24
|