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 ADDED
@@ -0,0 +1,3 @@
1
+ --title 'RSpecSolr Documentation'
2
+ lib/**/*.rb -
3
+ README.rdoc MATCHERS.rdoc LICENSE.txt
@@ -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
- * ("fld1" => "val1", "fld2" => "val2")
48
- NOTE: single Solr document must have all key value pairs
49
- * ("fldname" => ["val1", "val2", "val3"])
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" => "blue is best"}, {"fld" => "val"}])
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("f1" => "v1", "f2" => ["val1", "val2", "val3"])
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
- Provides RSpec custom matchers to be used with Solr response objects.
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 expecation_matchers.rdoc
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
- Array(doc[exp_fname]).include?(exp_val)
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)
@@ -1,3 +1,3 @@
1
1
  class RSpecSolr
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
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', 'expectation_matchers.rdoc']
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", "expectation_matchers.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"=>"val", "fld2"=>"val2"},
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 'should include(:key => "/regex/")' do
365
- it "does something" do
366
- pending "to be implemented"
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
- end
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.0
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-08-15 00:00:00.000000000 Z
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
- - expectation_matchers.rdoc
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: 2828541133057888426
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: 2828541133057888426
189
+ hash: -4597988063406856522
189
190
  requirements: []
190
191
  rubyforge_project:
191
192
  rubygems_version: 1.8.24