rspec-solr 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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