Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Custom RSPec matcher for detailed hash compasion and diff
require 'facets/hash/recurse'
# Usage:
# expect(actual).to match_hash(expected)
#
RSpec::Matchers.define :match_hash do |expected|
match do |actual|
# Sort hashes before comparing so that the diff only shows actual changes between keys and
# values.
actual = actual.recurse {|h| h.sort_by {|k,v| k.to_s }.to_h }
expected = expected.recurse {|h| h.sort_by {|k,v| k.to_s }.to_h }
is_match = actual == expected
unless is_match
system(
# If [diff-so-fancy](https://github.com/so-fancy/diff-so-fancy) is available, use it
if (system('which diff-so-fancy >/dev/null'); $?.success?)
"git diff $(echo '#{JSON.pretty_generate(expected)}' | git hash-object -w --stdin) " +
"$(echo '#{JSON.pretty_generate(actual )}' | git hash-object -w --stdin) | diff-so-fancy cat -"
else
"git diff $(echo '#{JSON.pretty_generate(expected)}' | git hash-object -w --stdin) " +
"$(echo '#{JSON.pretty_generate(actual )}' | git hash-object -w --stdin) --word-diff | cat -"
end,
out: $stdout,
err: :out
)
end
is_match
end
failure_message { 'Look at the Diff above! ^^^' }
end
@goodniceweb

This comment has been minimized.

Copy link

@goodniceweb goodniceweb commented Mar 23, 2020

NoMethodError: undefined method recurse' for {}:Hash`

@TylerRick

This comment has been minimized.

Copy link
Owner Author

@TylerRick TylerRick commented Mar 27, 2020

Good catch. I forgot I was using facets. Added:

require 'facets/hash/recurse'
@goodniceweb

This comment has been minimized.

Copy link

@goodniceweb goodniceweb commented Apr 8, 2020

thanks for explaining, very useful gist 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment