Class: RSpecSolr::SolrResponseHash

Inherits:
Hash
  • Object
show all
Defined in:
lib/rspec-solr/solr_response_hash.rb

Overview

Subclass Hash so we can use RSpec matchers for number of documents:

my_solr_resp_hash.should have(3).documents
my_solr_resp_hash.should have_at_least(3).documents

NOTE: to use has_document?(String) to match documents, set the id_field attribute (defaults to 'id')

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#id_fieldObject

id_field attribute defaults to 'id'


10
11
12
# File 'lib/rspec-solr/solr_response_hash.rb', line 10

def id_field
  @id_field
end

Instance Method Details

#doc_matches_all_criteria(doc, expectations_hash) ⇒ Object

return true if the document contains all the key value pairs in the expectations_hash


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rspec-solr/solr_response_hash.rb', line 66

def doc_matches_all_criteria(doc, expectations_hash)
  expectations_hash.all? do |exp_fname, exp_vals|
    doc.include?(exp_fname) &&
      # exp_vals can be a String or an Array
      # if it's an Array, then all expected values must be present
      Array(exp_vals).all? do |exp_val|
        # a doc's fld values can be a String or an Array
        case exp_val
        when Regexp
          Array(doc[exp_fname]).any? { |val| val =~ exp_val }
        else
          Array(doc[exp_fname]).include?(exp_val)
        end
      end
  end
end

#get_first_doc_index(expected_doc) ⇒ Object

Returns the index of the first document that meets the expectations in THIS response.

Examples:

expected_doc Hash implies ALL key/value pairs will be matched in a SINGLE Solr document

{"id" => "666"}
{"subject" => ["warm fuzzies", "fluffy"]}
{"title" => "warm fuzzies", "subject" => ["puppies"]}

expected_doc String

"666"  implies  {'id' => '666'}  when id_field is 'id'

expected_doc Array

["1", "2", "3"]  implies we expect Solr docs with ids 1, 2, 3 included in this response
[{"title" => "warm fuzzies"}, {"title" => "cool fuzzies"}]  implies we expect at least one Solr doc in this response matching each Hash in the Array

Parameters:

  • expected_doc

    what should be matched in a document in THIS response

Returns:

  • the index of the first document that meets the expectations in THIS response


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rspec-solr/solr_response_hash.rb', line 94

def get_first_doc_index(expected_doc)
  # FIXME:  DRY it up! -- very similar to has_document
  if expected_doc.is_a?(Hash)
    # we are happy if any doc meets all of our expectations
    docs.any? do |doc|
      expected_doc.all? do |exp_fname, exp_vals|
        if doc.include?(exp_fname) &&
           # exp_vals can be a String or an Array
           # if it's an Array, then all expected values must be present
           Array(exp_vals).all? do |exp_val|
             # a doc's fld values can be a String or an Array
             Array(doc[exp_fname]).include?(exp_val)
           end
          first_doc_index = get_min_index(first_doc_index, docs.find_index(doc))
          return first_doc_index
        end
      end
    end
  elsif expected_doc.is_a?(String)
    first_doc_index = get_min_index(first_doc_index, get_first_doc_index(id_field => expected_doc))
  elsif expected_doc.is_a?(Array)
    expected_doc.all? do |exp|
      ix = get_first_doc_index(exp)
      if ix
        first_doc_index = get_min_index(first_doc_index, ix)
      else
        return nil
      end
    end
  end

  first_doc_index
end

#has_document?(expected_doc, max_doc_position = nil, all_must_match = nil) ⇒ Boolean

Returns true if THIS Solr Response contains document(s) as indicated by expected_doc.

Examples:

expected_doc Hash implies ALL key/value pairs will be matched in a SINGLE Solr document

{"id" => "666"}
{"subject" => ["warm fuzzies", "fluffy"]}
{"title" => "warm fuzzies", "subject" => ["puppies"]}

expected_doc String

"666"  implies  {'id' => '666'}  when id_field is 'id'

expected_doc Array

["1", "2", "3"]  implies we expect Solr docs with ids 1, 2, 3 included in this response
[{"title" => "warm fuzzies"}, {"title" => "cool fuzzies"}]  implies we expect at least one Solr doc in this response matching each Hash in the Array
[{"title" => /rm fuzz/}, {"title" => /^cool/}]  implies we expect at least one Solr doc in this response matching each Hash in the Array

Parameters:

  • expected_doc

    what should be matched in a document in THIS response

  • max_doc_position (FixNum) (defaults to: nil)

    maximum acceptable position (1-based) of document in results. (e.g. if 2, it must be the 1st or 2nd doc in the results)

Returns:

  • (Boolean)

    true if THIS Solr Response contains document(s) as indicated by expected_doc


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rspec-solr/solr_response_hash.rb', line 39

def has_document?(expected_doc, max_doc_position = nil, all_must_match = nil)
  if expected_doc.is_a?(Hash)
    if all_must_match
      first_non_match = docs.find_index { |doc| !doc_matches_all_criteria(doc, expected_doc) }
      (first_non_match ? first_non_match >= max_doc_position : true)
    else
      # we are happy if any doc meets all of our expectations
      docs.any? do |doc|
        doc_matches_all_criteria(doc, expected_doc) &&
          # satisfy doc's position in the results
          (max_doc_position ? docs.find_index(doc) < max_doc_position : true)
      end
    end
  elsif expected_doc.is_a?(String)
    if all_must_match
      fail ArgumentError, 'in_each_of_first(n) requires a Hash argument to include() method'
    end
    has_document?({ id_field => expected_doc }, max_doc_position)
  elsif expected_doc.is_a?(Array)
    if all_must_match
      fail ArgumentError, 'in_each_of_first(n) requires a Hash argument to include() method'
    end
    expected_doc.all? { |exp| has_document?(exp, max_doc_position) }
  end
end

#has_facet_field?(ff_name) ⇒ Boolean

Returns true if the Solr response contains the facet field indicated and the facet field has some values; return false otherwise.

Returns:

  • (Boolean)

    true if the Solr response contains the facet field indicated and the facet field has some values; return false otherwise


150
151
152
153
154
155
156
# File 'lib/rspec-solr/solr_response_hash.rb', line 150

def has_facet_field?(ff_name)
  if self['facet_counts'] && self['facet_counts']['facet_fields'] && self['facet_counts']['facet_fields'][ff_name]
    self['facet_counts']['facet_fields'][ff_name]
  else
    false
  end
end

#has_facet_field_with_value?(ff_name, facet_val = nil) ⇒ Boolean

Returns true if the Solr response contains the facet field indicated and the facet field has some values; return false otherwise.

Returns:

  • (Boolean)

    true if the Solr response contains the facet field indicated and the facet field has some values; return false otherwise


136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/rspec-solr/solr_response_hash.rb', line 136

def has_facet_field_with_value?(ff_name, facet_val = nil)
  if self['facet_counts'] && self['facet_counts']['facet_fields'] && self['facet_counts']['facet_fields'][ff_name]
    if facet_val
      val_count_array = self['facet_counts']['facet_fields'][ff_name]
      return val_count_array.each_slice(2).find { |val_count| val_count[0] == facet_val }
    else
      self['facet_counts']['facet_fields'][ff_name].size > 0
    end
  else
    false
  end
end

#num_docs_partial_output_strObject

Returns String containing response header and numFound parts of hash for readable output for number of docs messages.

Returns:

  • String containing response header and numFound parts of hash for readable output for number of docs messages


129
130
131
132
133
# File 'lib/rspec-solr/solr_response_hash.rb', line 129

def num_docs_partial_output_str
  "{'responseHeader' => #{self['responseHeader'].inspect}, " +
    (self['response'] ? "'response' => {'numFound' => #{self['response']['numFound']}, ...}" : '') +
    ' ... }'
end

#sizeObject

NOTE: this is about the TOTAL number of Solr documents matching query, not the number of docs in THIS response override Hash size method so we can use RSpec matchers for number of documents:

my_solr_resp_hash.should have(3).documents
my_solr_resp_hash.should have_at_least(3).documents

21
22
23
24
# File 'lib/rspec-solr/solr_response_hash.rb', line 21

def size
  self['response'] ? self['response']['numFound'] : 0  # total number of Solr docs matching query
  # NOT:  self["response"]["docs"].size  # number of Solr docs returned in THIS response
end