Created
February 2, 2012 00:54
-
-
Save jsmestad/1720538 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require File.expand_path('../exceptions', __FILE__) | |
# Supports the following matchers: | |
# | |
# describe '/api/account.json' do | |
# subject { json_response } | |
# before { get '/api/account.json' } | |
# it { should have_json(:email).of_type(String) } | |
# it { should have_json(:posts).of_type(Array).inside_of('account') } | |
# it { should have_json(:review).of_type(Hash).inside_of('account/profile') } | |
# end | |
# | |
RSpec::Matchers.define :have_json do |name| | |
diffable | |
match do |json| | |
begin | |
@obj = value_at_json_path(json, @path)["#{name}"] | |
@obj != nil && (@type_class.present? ? @obj.kind_of?(@type_class) : true) | |
rescue Response::Matchers::MissingPathError | |
false | |
end | |
end | |
chain :of_type do |type_class| | |
@type_class = type_class | |
end | |
chain :inside_of do |path| | |
@path = path | |
end | |
failure_message_for_should do |json| | |
message = "expected JSON signature to include attribute '#{name}'" | |
message << %( of type #{@type_class}) if @type_class | |
message << %( at path "#{@path}") if @path | |
message << %(, but it was #{@obj.inspect}) | |
message | |
end | |
failure_message_for_should_not do |json| | |
message = "expected JSON signature to exclude attribute '#{name}'" | |
message << %( of type #{@type_class}) if @type_class | |
message << %( at path "#{@path}") if @path | |
message << %(, but it was #{@obj.inspect}) | |
message | |
end | |
description do | |
message = "contain the JSON signature for '#{name.to_s}'" | |
message << %( of type #{@type_class}) if @type_class.present? | |
message << %( at path "#{@path}") if @path.present? | |
message | |
end | |
# Begin internal helpers | |
def value_at_json_path(json, path) | |
return json unless path | |
json_path_to_keys(path).inject(json) do |value, key| | |
case value | |
when Hash, Array then value.fetch(key){ missing_json_path!(path) } | |
else missing_json_path!(path) | |
end | |
end | |
end | |
def json_path_to_keys(path) | |
path.split("/").map{|k| k =~ /^\d+$/ ? k.to_i : k } | |
end | |
def missing_json_path!(path) | |
raise Response::Matchers::MissingPathError.new(path) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output looks like