require 'spec_helper' describe "Koala::Facebook::API" do before :each do @service = Koala::Facebook::API.new end let(:dummy_response) { double("fake response", data: {}, status: 200, body: "", headers: {}) } it "doesn't include an access token if none was given" do expect(Koala).to receive(:make_request).with( anything, hash_not_including('access_token' => 1), anything, anything ).and_return(Koala::HTTPService::Response.new(200, "", "")) @service.api('anything') end it "includes an access token if given" do token = 'adfadf' service = Koala::Facebook::API.new token expect(Koala).to receive(:make_request).with( anything, hash_including('access_token' => token), anything, anything ).and_return(Koala::HTTPService::Response.new(200, "", "")) service.api('anything') end it "doesn't add token to received arguments" do token = 'adfadf' service = Koala::Facebook::API.new token expect(Koala).to receive(:make_request).with( anything, hash_including('access_token' => token), anything, anything ).and_return(Koala::HTTPService::Response.new(200, "", "")) args = {}.freeze service.api('anything', args) end it "has an attr_reader for access token" do token = 'adfadf' service = Koala::Facebook::API.new token expect(service.access_token).to eq(token) end it "has an attr_reader for app_secret" do secret = double service = Koala::Facebook::API.new(@token, secret) expect(service.app_secret).to eq(secret) end it "turns arrays of non-enumerables into comma-separated arguments by default" do args = [12345, {:foo => [1, 2, "3", :four]}] expected = ["/12345", {:foo => "1,2,3,four"}, "get", {}] response = double('Mock KoalaResponse', :body => '', :status => 200) expect(Koala).to receive(:make_request).with(*expected).and_return(response) @service.api(*args) end it "can be configured to leave arrays of non-enumerables as is" do Koala.configure do |config| config.preserve_form_arguments = true end args = [12345, {:foo => [1, 2, "3", :four]}] expected = ["/12345", {:foo => [1, 2, "3", :four]}, "get", {}] response = double('Mock KoalaResponse', :body => '', :status => 200) expect(Koala).to receive(:make_request).with(*expected).and_return(response) @service.api(*args) end it "can be configured on a per-request basis to leave arrays as is" do args = [12345, {foo: [1, 2, "3", :four]}, "get", preserve_form_arguments: true] expected = ["/12345", {foo: [1, 2, "3", :four]}, "get", preserve_form_arguments: true] response = double('Mock KoalaResponse', :body => '', :status => 200) expect(Koala).to receive(:make_request).with(*expected).and_return(response) @service.api(*args) end it "doesn't turn arrays containing enumerables into comma-separated strings" do params = {:foo => [1, 2, ["3"], :four]} args = [12345, params] # we leave this as is -- the HTTP layer can either handle it appropriately # (if appropriate behavior is defined) # or raise an exception expected = ["/12345", params, "get", {}] response = double('Mock KoalaResponse', :body => '', :status => 200) expect(Koala).to receive(:make_request).with(*expected).and_return(response) @service.api(*args) end it "doesn't modify any data if the option format of :json is provided" do args = [12345, {:foo => [1, 2, "3", :four]}, 'get', format: :json] expected = ["/12345", {:foo => [1, 2, "3", :four]}, 'get', format: :json] response = double('Mock KoalaResponse', :body => '', :status => 200) expect(Koala).to receive(:make_request).with(*expected).and_return(response) @service.api(*args) end it "raises an API error if the HTTP response code is greater than or equal to 500" do allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(500, 'response body', {})) expect { @service.api('anything') }.to raise_exception(Koala::Facebook::APIError) end describe "path manipulation" do context "leading /" do it "adds a leading / to the path if not present" do path = "anything" expect(Koala).to receive(:make_request).with("/#{path}", anything, anything, anything).and_return(Koala::HTTPService::Response.new(200, 'true', {})) @service.api(path) end it "doesn't change the path if a leading / is present" do path = "/anything" expect(Koala).to receive(:make_request).with(path, anything, anything, anything).and_return(Koala::HTTPService::Response.new(200, 'true', {})) @service.api(path) end end end describe "with an access token" do before(:each) do @api = Koala::Facebook::API.new(@token) @app_access_token = KoalaTest.app_access_token end it_should_behave_like "Koala GraphAPI" it_should_behave_like "Koala GraphAPI with an access token" it_should_behave_like "Koala GraphAPI with GraphCollection" end describe "without an access token" do before(:each) do @api = Koala::Facebook::API.new end # In theory this should behave the same with a GraphCollection, but those tests currently hit # an endpoint that now requires a token. it_should_behave_like "Koala GraphAPI" it_should_behave_like "Koala GraphAPI without an access token" end context '#api' do let(:access_token) { 'access_token' } let(:api) { Koala::Facebook::API.new(access_token) } let(:path) { '/path' } let(:appsecret) { 'appsecret' } let(:token_args) { { 'access_token' => access_token } } let(:appsecret_proof_args) { { 'appsecret_proof' => OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), appsecret, access_token) } } let(:verb) { 'get' } let(:response) { Koala::HTTPService::Response.new(200, '', '') } describe "the appsecret_proof arguments" do describe "with an API access token present" do describe "and with an appsecret included on API initialization " do let(:api) { Koala::Facebook::API.new(access_token, appsecret) } it "will be included by default" do expect(Koala).to receive(:make_request).with(path, token_args.merge(appsecret_proof_args), verb, {}).and_return(response) api.api(path, {}, verb, :appsecret_proof => true) end end describe "but without an appsecret included on API initialization" do it "will not be included" do expect(Koala).to receive(:make_request).with(path, token_args, verb, {}).and_return(response) api.api(path, {}, verb, :appsecret_proof => true) end end end describe "but without an API access token present" do describe "and with an appsecret included on API initialization " do let(:api) { Koala::Facebook::API.new(nil, appsecret) } it "will not be included" do expect(Koala).to receive(:make_request).with(path, {}, verb, {}).and_return(response) api.api(path, {}, verb, :appsecret_proof => true) end end describe "but without an appsecret included on API initialization" do let(:api) { Koala::Facebook::API.new } it "will not be included" do expect(Koala).to receive(:make_request).with(path, {}, verb, {}).and_return(response) api.api(path, {}, verb, :appsecret_proof => true) end end end end end describe "#graph_call" do it "passes all arguments to the api method" do user = KoalaTest.user1 args = {} verb = 'get' opts = {:a => :b} expect(@service).to receive(:api).with(user, args, verb, opts).and_return(dummy_response) @service.graph_call(user, args, verb, opts) end it "throws an APIError if the result hash has an error key" do allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(500, '{"error": "An error occurred!"}', {})) expect { @service.graph_call(KoalaTest.user1, {}) }.to raise_exception(Koala::Facebook::APIError) end it "passes the results through GraphCollection.evaluate" do allow(@service).to receive(:api).and_return(dummy_response) expect(Koala::Facebook::API::GraphCollection).to receive(:evaluate).with(dummy_response.data, @service) @service.graph_call("/me") end it "returns the results of GraphCollection.evaluate" do expected = {} allow(@service).to receive(:api).and_return(dummy_response) expect(Koala::Facebook::API::GraphCollection).to receive(:evaluate).and_return(expected) expect(@service.graph_call("/me")).to eq(expected) end it "returns the post_processing block's results if one is supplied" do other_result = [:a, 2, :three] block = Proc.new {|r| other_result} allow(@service).to receive(:api).and_return(dummy_response) expect(@service.graph_call("/me", {}, "get", {}, &block)).to eq(other_result) end it "gets the status of a Koala::HTTPService::Response if requested" do response = Koala::HTTPService::Response.new(200, '', {}) allow(Koala).to receive(:make_request).and_return(response) expect(@service.graph_call('anything', {}, 'get', http_component: :status)).to eq(200) end it "gets the headers of a Koala::HTTPService::Response if requested" do headers = {"a" => 2} response = Koala::HTTPService::Response.new(200, '', headers) allow(Koala).to receive(:make_request).and_return(response) expect(@service.graph_call('anything', {}, 'get', :http_component => :headers)).to eq(headers) end it "returns the entire response if http_component => :response" do http_component = :response response = Koala::HTTPService::Response.new(200, '', {}) allow(Koala).to receive(:make_request).and_return(response) expect(@service.graph_call('anything', {}, 'get', :http_component => http_component)).to eq(response) end it "returns the body of the request as JSON if no http_component is given" do result = {"a" => 2} response = Koala::HTTPService::Response.new(200, result.to_json, {}) allow(Koala).to receive(:make_request).and_return(response) expect(@service.graph_call('anything')).to eq(result) end it "handles rogue true/false as responses" do expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'true', {})) expect(@service.graph_call('anything')).to be_truthy expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'false', {})) expect(@service.graph_call('anything')).to be_falsey end end end