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