Rspec Candies and Cookies

it "include_hash tests nested hashes" do
 { foo: 'a', bar: {nested_hash: {fi: 'c', baz:'b'} }}.should include_nested_hash(nested_hash: {fi: 'c', baz:'b'})
 end

Combining Mandraka’s  Rspec Candy with this little find from CookiesHQ, led me to a nested hash matcher

Very useful for testing API responses.


def find_first_value_for(hsh, key)
 return hsh[key] if hsh[key]
 hsh.values.each do |hash_value|
   values = [hash_value] unless hash_value.is_a? Array
   values.each{ |value|   return find_first_value_for(value, key) if value.is_a? Hash }
 end
end

RSpec::Matchers.define :include_nested_hash do |expected|
 match do |actual|
   if !actual.nil? and expected.is_a? Hash
     if expected.keys.count > 1
       keys.map do |key|
         value = find_first_value_for actual(actual, key)
         !value.nil? ? {key.to_sym => value} : {}
       end
     elsif expected.keys.count == 1
      {expected.keys.first => find_first_value_for(actual, expected.keys.first)}
     else
      {}
     end
     !actual.nil? && result == expected
   else
     false
   end
 end
end

Just include it in your spec_helper.rb or custom matcher module then test with something like this:

context "when testing with rspec candy" do
 it "include_hash is available" do
 { foo: 'a', bar: 'b' }.should include_hash(foo: 'a')
 end
 it "include_hash tests nested hashes" do
 { foo: 'a', bar: {nested_hash: {fi: 'c', baz:'b'} }}.should include_nested_hash(nested_hash: {fi: 'c', baz:'b'})
 end
end

Author: ashr

father, husband, travel junkie, recovering startup-addict, cto, data scientist and programmer.

1 thought on “Rspec Candies and Cookies”

  1. Thanks for the pointer. That’ll help if I need to cernovt anything else. I’m impressed by how much Rspec has changed in just the last couple of months. I think the older release I was working from dates back only as far as the start of April.

Leave a Reply