Skip to content

Instantly share code, notes, and snippets.

@TylerRick
Forked from fabriciofreitag/detailed_hash_diff.rb
Last active July 22, 2022 18:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TylerRick/fd77ff6b7f8ce53148cdd67dae26e6a5 to your computer and use it in GitHub Desktop.
Save TylerRick/fd77ff6b7f8ce53148cdd67dae26e6a5 to your computer and use it in GitHub Desktop.
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
Copy link

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

@TylerRick
Copy link
Author

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

require 'facets/hash/recurse'

@goodniceweb
Copy link

thanks for explaining, very useful gist 👍

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