Skip to content

Commit

Permalink
allow recursion to continue. improved implementation to handle more c…
Browse files Browse the repository at this point in the history
…omplex JSON.
  • Loading branch information
sorens committed Sep 5, 2012
1 parent 7cbdb4f commit a7cdbe6
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -15,3 +15,4 @@ spec/reports
test/tmp
test/version_tmp
tmp
*.DS_Store
22 changes: 20 additions & 2 deletions lib/api_matchers/core/find_in_json.rb
Expand Up @@ -9,14 +9,32 @@ def initialize(json)

def find(options={})
expected_key = options.fetch(:node).to_s
expected_value = options.fetch(:value).to_s if options.has_key? :value

@json.each do |key, value|
if key == expected_key
return value
if value == expected_value or ! expected_value.present?
return value
end
end
# do we have more to recurse through?
keep_going = nil
if value.is_a? Hash
return FindInJSON.new(value).find(node: expected_key)
keep_going = value # hash, keep going
elsif value.is_a? Array
keep_going = value # an array, keep going
elsif value.nil? and key.is_a? Hash
keep_going = key # the array was passed in and now in the key, keep going
end

if keep_going
begin
# ignore nodes where the key doesn't match
return FindInJSON.new(keep_going).find(node: expected_key, value: expected_value)
rescue ::APIMatchers::Core::Exceptions::KeyNotFound
end
end

end
raise ::APIMatchers::Core::Exceptions::KeyNotFound.new( "key was not found" ) # we did not find the requested key
end
Expand Down
8 changes: 7 additions & 1 deletion lib/api_matchers/response_body/have_json_node.rb
Expand Up @@ -13,7 +13,13 @@ def matches?(actual)
end

begin
node = Core::FindInJSON.new(json).find(node: @expected_node.to_s)
options = {}
options[:node] = @expected_node.to_s
if @with_value.present?
options[:value] = @with_value
end

node = Core::FindInJSON.new(json).find( options )

if @with_value
node.to_s == @with_value.to_s
Expand Down
75 changes: 57 additions & 18 deletions spec/api_matchers/response_body/have_json_node_spec.rb
Expand Up @@ -47,24 +47,63 @@
end

context 'expected key and value in more deep in the JSON' do
it "should pass when the expected key exist" do
{ :transaction => { :id => 150 } }.to_json.should have_json_node(:id)
end

it "should pass when the expected key and expected value exist" do
{ :transaction => { :error => { :code => '999' } } }.to_json.should have_json_node(:code).with('999')
end

it "should fail when the expected key does not exist" do
expect {
{ :transaction => { :id => 150, :error => {} } }.to_json.should have_json_node(:code)
}.to fail_with(%Q{expected to have node called: 'code'. Got: '{"transaction":{"id":150,"error":{}}}'})
end

it "should fail when the expected key exist but don't exist the expected value" do
expect {
{ :transaction => { :id => 150, :error => { :code => '999' } } }.to_json.should have_json_node(:code).with('001')
}.to fail_with(%Q{expected to have node called: 'code' with value: '001'. Got: '{"transaction":{"id":150,"error":{"code":"999"}}}'})
context '.to_json used' do
it "should pass when the expected key exist" do
{ :transaction => { :id => 150 } }.to_json.should have_json_node(:id)
end

it "should pass when the expected key and expected value exist" do
{ :transaction => { :error => { :code => '999' } } }.to_json.should have_json_node(:code).with('999')
end

it "should pass when the expected key and expected value exist in very deep" do
{ :first=>"A", :second=>nil, :third=>{ :stuff => { :first_stuff=>{ :color=>"green", :size=>"small", :shape=>"circle", :uid=>"first_stuff"}, :second_stuff=>{ :color=>"blue", :size=>"large", :shape=>"square", :uid=>"second_stuff"}}, :junk=>[{"name"=>"junk_one", :uid=>"junk_one", :stuff_uid=>"first_stuff"}, { :name=>"junk_two", :uid=>"junk_two", :stuff_uid=>"second_stuff"}]}}.to_json.should have_json_node( :junk )
end

it "should pass when the expected key and expected value exist in very deep" do
{ :first=>"A", :second=>nil, :third=>{ :stuff => { :first_stuff=>{ :color=>"green", :size=>"small", :shape=>"circle", :uid=>"first_stuff"}, :second_stuff=>{ :color=>"blue", :size=>"large", :shape=>"square", :uid=>"second_stuff"}}, :junk=>[{"name"=>"junk_one", :uid=>"junk_one", :stuff_uid=>"first_stuff"}, { :name=>"junk_two", :uid=>"junk_two", :stuff_uid=>"second_stuff"}]}}.to_json.should have_json_node( :name ).with( "junk_two" )
end

it "should fail when the expected key does not exist" do
expect {
{ :transaction => { :id => 150, :error => {} } }.to_json.should have_json_node(:code)
}.to fail_with(%Q{expected to have node called: 'code'. Got: '{"transaction":{"id":150,"error":{}}}'})
end

it "should fail when the expected key exist but don't exist the expected value" do
expect {
{ :transaction => { :id => 150, :error => { :code => '999' } } }.to_json.should have_json_node(:code).with('001')
}.to fail_with(%Q{expected to have node called: 'code' with value: '001'. Got: '{"transaction":{"id":150,"error":{"code":"999"}}}'})
end
end
context 'json string used' do
it "should pass when the expected key exist" do
'{ "transaction": {"id": 150 } }'.should have_json_node(:id)
end

it "should pass when the expected key and expected value exist" do
'{ "transaction": {"error": { "code": "999" } } }'.should have_json_node(:code).with('999')
end

it "should pass when the expected key and expected value exist in very deep" do
'{"first":"A","second":null,"third":{"stuff":{"first_stuff":{"color":"green","size":"small","shape":"circle","uid":"first_stuff"},"second_stuff":{"color":"blue","size":"large","shape":"square","uid":"second_stuff"}},"junk":[{"name":"junk_one","uid":"junk_one","stuff_uid":"first_stuff"},{"name":"junk_two","uid":"junk_two","stuff_uid":"second_stuff"}]}}'.should have_json_node( :junk )
end

it "should pass when the expected key and expected value exist in very deep" do
'{"first":"A","second":null,"third":{"stuff":{"first_stuff":{"color":"green","size":"small","shape":"circle","uid":"first_stuff"},"second_stuff":{"color":"blue","size":"large","shape":"square","uid":"second_stuff"}},"junk":[{"name":"junk_one","uid":"junk_one","stuff_uid":"first_stuff"},{"name":"junk_two","uid":"junk_two","stuff_uid":"second_stuff"}]}}'.should have_json_node( :name ).with( "junk_two" )
end

it "should fail when the expected key does not exist" do
expect {
'{"transaction":{"id":150,"error":{}}}'.should have_json_node(:code)
}.to fail_with(%Q{expected to have node called: 'code'. Got: '{"transaction":{"id":150,"error":{}}}'})
end

it "should fail when the expected key exist but don't exist the expected value" do
expect {
'{"transaction":{"id":150,"error":{"code":"999"}}}'.should have_json_node(:code).with('001')
}.to fail_with(%Q{expected to have node called: 'code' with value: '001'. Got: '{"transaction":{"id":150,"error":{"code":"999"}}}'})
end
end
end

Expand Down

0 comments on commit a7cdbe6

Please sign in to comment.