require 'spec_helper'
describe APIMatchers::ResponseBody::HaveJsonNode do
describe "actual.should have_json_node" do
context 'expected key and value in top level' do
it "pass when the expected key exist" do
{ :product => 'gateway' }.to_json.should have_json_node(:product)
end
it "fail when the expected key does not exist" do
expect {
{ :product => 'pabx' }.to_json.should have_json_node(:developers)
}.to fail_with(%Q{expected to have node called: 'developers'. Got: '{"product":"pabx"}'})
end
it "pass when the expected key exist with the expected value" do
{ :product => 'payment-gateway' }.to_json.should have_json_node(:product).with('payment-gateway')
end
it "pass when the expected key exist with the expected value (as integer)" do
{ :number => 1 }.to_json.should have_json_node(:number).with(1)
end
it "pass when the expected key exist with the expected value (as boolean, true)" do
{ :number => true }.to_json.should have_json_node(:number).with(true)
end
it "pass when the expected key exist with the expected value (as boolean, false)" do
{ :number => false }.to_json.should have_json_node(:number).with(false)
end
it "pass when the expected key exist but the expected value is wrong (as boolean, true)" do
{ :number => true }.to_json.should_not have_json_node(:number).with(false)
end
it "pass when the expected key exist but the expected value is wrong (as boolean, false)" do
{ :number => false }.to_json.should_not have_json_node(:number).with(true)
end
it "pass when the expected key exists with the expected value (as DateTime)" do
now = DateTime.now
{ :date => now }.to_json.should have_json_node(:date).with(now)
end
it "pass when the expected key exists with the expected value (as Date)" do
now = Date.today
{ :date => now }.to_json.should have_json_node(:date).with(now)
end
it "pass when the expected key exists with the expected value (as Time)" do
now = Time.now
{ :time => now }.to_json.should have_json_node(:time).with(now)
end
it "fail when the expected key exist but the expected value don't exist" do
expect {
{ :product => 'payment-gateway' }.to_json.should have_json_node(:product).with('email-marketing')
}.to fail_with(%Q{expected to have node called: 'product' with value: 'email-marketing'. Got: '{"product":"payment-gateway"}'})
end
it "not parse the matcher for json when you pass a xml" do
expect {
"webdesk".should have_json_node(:name).with('webdesk')
}.to raise_error(APIMatchers::InvalidJSON, "Invalid JSON: 'webdesk'")
end
end
context 'expected key and nil value' do
it "pass when the expected key exists" do
{ :product => nil }.to_json.should have_json_node(:product)
end
it "pass when the expected key exists and the expected value is nil" do
{ :product => nil }.to_json.should have_json_node(:product).with( nil )
end
it "fail when the expected key exist but the expected value don't exist" do
expect {
{ :product => nil }.to_json.should have_json_node(:product).with('email-marketing')
}.to fail_with(%Q{expected to have node called: 'product' with value: 'email-marketing'. Got: '{"product":null}'})
end
end
context 'expected key and value in more deep in the JSON' do
context '.to_json used' do
it "pass when the expected key exist" do
{ :transaction => { :id => 150 } }.to_json.should have_json_node(:id)
end
it "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 "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 "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 "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 "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 "pass when the expected key exist" do
'{ "transaction": {"id": 150 } }'.should have_json_node(:id)
end
it "pass when the expected key and expected value exist" do
'{ "transaction": {"error": { "code": "999" } } }'.should have_json_node(:code).with('999')
end
it "pass when the expected key exist with the expected value (as integer)" do
'{"number":1 }'.should have_json_node(:number).with(1)
end
it "pass when the expected key exist with the expected value (as boolean)" do
'{"boolean":true}'.should have_json_node(:boolean).with(true)
end
it "pass when the expected key exists with the expected value (as DateTime)" do
now = DateTime.parse( "2012-09-18T15:42:12-07:00" )
'{"date": "2012-09-18T15:42:12-07:00"}'.should have_json_node(:date).with(now)
end
it "pass when the expected key exists with the expected value (as Date)" do
now = Date.parse( "2012-09-18" )
'{"date": "2012-09-18"}'.should have_json_node(:date).with(now)
end
it "pass when the expected key exists with the expected value (as Time)" do
now = Time.parse("2012-09-18T15:42:12Z")
'{"time": "2012-09-18T15:42:12+00:00"}'.should have_json_node(:time).with(now)
end
it "pass when the expected key exist with the expected value (as boolean) in a multi node" do
'{"uid":"123456","boolean":true}'.should have_json_node(:boolean).with(true)
end
it "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 "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 "pass when the expected key and including text exist" do
'{"Key":"A=123456-abcdef-09876-ghijkl; path=/; expires=Sun, 05-Sep-2032 05:50:39 GMT\nB=ABCDEF123456; path=/; expires=Sun, 05-Sep-2032 05:50:39 GMT", "Content-Type":"application/json; charset=utf-8"}'.should have_json_node( "Key" ).including_text( "123456-abcdef-09876-ghijkl" )
end
it "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 "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
context "including_text" do
it "pass when the expected is included in the actual" do
{ :transaction => { :error => { :message => "Transaction error: Name can't be blank" } } }.to_json.should have_json_node(:message).including_text("Transaction error")
end
it "fail when the expected is not included in the actual" do
expect {
{ :transaction => { :error => { :message => "Transaction error: Name can't be blank" } } }.to_json.should have_json_node(:message).including_text("Fox on the run")
}.to fail_with(%Q{expected to have node called: 'message' including text: 'Fox on the run'. Got: '{"transaction":{"error":{"message":"Transaction error: Name can't be blank"}}}'})
end
end
end
describe "actual.should_not have_json_node" do
it "pass when don't have the expected node in root level" do
{ :product => 'gateway' }.to_json.should_not have_json_node(:status)
end
it "pass when don't have the expected node in any level" do
{ :transaction => { :id => 12, :status => 'paid' } }.to_json.should_not have_json_node(:error)
end
it "fail when the expected key exist" do
expect {
{ :status => 'paid' }.to_json.should_not have_json_node(:status)
}.to fail_with(%Q{expected to NOT have node called: 'status'. Got: '{"status":"paid"}'})
end
it "pass when have the expected key but have a different value" do
{ :status => 'paid' }.to_json.should_not have_json_node(:status).with('not_authorized')
end
it "fail when have the expected key and have the expected value" do
expect {
{ :status => 'paid' }.to_json.should_not have_json_node(:status).with('paid')
}.to fail_with(%Q{expected to NOT have node called: 'status' with value: 'paid'. Got: '{"status":"paid"}'})
end
context "including_text" do
it "pass when the expected is NOT included in the actual" do
{ :transaction => { :error => { :message => "Transaction error: Name can't be blank" } } }.to_json.should_not have_json_node(:message).including_text("Love gun")
end
it "fail when the expected is included in the actual" do
expect {
{ :transaction => { :error => { :message => "Transaction error: Name can't be blank" } } }.to_json.should_not have_json_node(:message).including_text("Transaction error")
}.to fail_with(%Q{expected to NOT have node called: 'message' including text: 'Transaction error'. Got: '{"transaction":{"error":{"message":"Transaction error: Name can't be blank"}}}'})
end
end
end
describe "some assumptions" do
it "pass when have the json node name" do
'{ "transaction": { "id": 54, "status": "paid" } }'.should have_json_node(:transaction)
end
it "pass when have json node with integer value" do
'{ "transaction": { "id": 54, "status": "paid" } }'.should have_json_node(:id).with(54)
end
it "should have json node including text" do
'{"error": "Transaction error: Name cant be blank"}'.should have_json_node(:error).including_text("Transaction error")
end
it "pass have json node with boolean value" do
'{"creditcard": true}'.should have_json_node(:creditcard).with(true)
end
it "pass have json node with string" do
'{ "error": "not_authorized", "transaction": { "id": "55" } }'.should have_node(:error).with('not_authorized')
end
it "pass have json node with integer" do
'{"parcels": 1 }'.should have_node(:parcels).with(1)
end
end
describe "with change configuration" do
before do
APIMatchers.setup { |config| config.response_body_method = :response_body }
end
after do
APIMatchers.setup { |config| config.response_body_method = nil }
end
it "pass if the actual.http_status is equal to 400" do
response = OpenStruct.new(:response_body => { :foo => :bar }.to_json)
response.should have_json_node(:foo).with('bar')
end
it "fail if the actual.http_status is not equal to 400" do
response = OpenStruct.new(:response_body => { :baz => :foo}.to_json)
expect { response.should have_json_node(:bar) }.to fail_with(%Q{expected to have node called: 'bar'. Got: '{"baz":"foo"}'})
end
end
end