require File.expand_path("../../spec_helper", __FILE__) describe Instagram::API do before do @keys = Instagram::Configuration::VALID_OPTIONS_KEYS end context "with module configuration" do before do Instagram.configure do |config| @keys.each do |key| config.send("#{key}=", key) end end end after do Instagram.reset end it "should inherit module configuration" do api = Instagram::API.new @keys.each do |key| expect(api.send(key)).to eq(key) end end context "with class configuration" do before do @configuration = { access_token: "AT", adapter: :typhoeus, client_id: "CID", client_secret: "CS", client_ips: "1.2.3.4", connection_options: { ssl: { verify: true } }, redirect_uri: "http://http://localhost:4567/oauth/callback", endpoint: "http://tumblr.com/", format: :xml, proxy: "http://shayne:sekret@proxy.example.com:8080", scope: "comments relationships", user_agent: "Custom User Agent", no_response_wrapper: true, loud_logger: true, sign_requests: false, } end context "during initialization" it "should override module configuration" do api = Instagram::API.new(@configuration) @keys.each do |key| expect(api.send(key)).to eq(@configuration[key]) end end context "after initilization" do let(:api) { Instagram::API.new } before do @configuration.each do |key, value| api.send("#{key}=", value) end end it "should override module configuration after initialization" do @keys.each do |key| expect(api.send(key)).to eq(@configuration[key]) end end describe "#connection" do it "should use the connection_options" do expect(Faraday::Connection).to receive(:new).with(include(ssl: { verify: true })) api.send(:connection) end end end end end describe "#config" do subject { Instagram::API.new } let(:config) do c = {}; @keys.each { |key| c[key] = key }; c end it "returns a hash representing the configuration" do @keys.each do |key| subject.send("#{key}=", key) end expect(subject.config).to eq(config) end end describe ".authorize_url" do it "should generate an authorize URL with necessary params" do params = { client_id: "CID", client_secret: "CS" } client = Instagram::Client.new(params) redirect_uri = "http://localhost:4567/oauth/callback" url = client.authorize_url(redirect_uri: redirect_uri) options = { redirect_uri: redirect_uri, response_type: "code", } params2 = client.send(:authorization_params).merge(options) url2 = client.send(:connection).build_url("/oauth/authorize/", params2).to_s expect(url2).to eq(url) end it "should not include client secret in URL params" do params = { client_id: "CID", client_secret: "CS" } client = Instagram::Client.new(params) redirect_uri = "http://localhost:4567/oauth/callback" url = client.authorize_url(redirect_uri: redirect_uri) expect(url).not_to include("client_secret") end describe "scope param" do it "should include the scope if there is one set" do params = { scope: "comments likes" } client = Instagram::Client.new(params) redirect_uri = "http://localhost:4567/oauth/callback" url = client.authorize_url(redirect_uri: redirect_uri) expect(url).to include("scope") end it "should not include the scope if the scope is blank" do params = { scope: "" } client = Instagram::Client.new(params) redirect_uri = "http://localhost:4567/oauth/callback" url = client.authorize_url(redirect_uri: redirect_uri) expect(url).not_to include("scope") end end describe "redirect_uri" do it "should fall back to configuration redirect_uri if not passed as option" do redirect_uri = "http://localhost:4567/oauth/callback" params = { redirect_uri: redirect_uri } client = Instagram::Client.new(params) url = client.authorize_url expect(url).to match(/redirect_uri=#{URI.escape(redirect_uri, Regexp.union('/', ':'))}/) end it "should override configuration redirect_uri if passed as option" do redirect_uri_config = "http://localhost:4567/oauth/callback_config" params = { redirect_uri: redirect_uri_config } client = Instagram::Client.new(params) redirect_uri_option = "http://localhost:4567/oauth/callback_option" options = { redirect_uri: redirect_uri_option } url = client.authorize_url(options) expect(url).to match(/redirect_uri=#{URI.escape(redirect_uri_option, Regexp.union('/', ':'))}/) end end end describe ".get_access_token" do describe "common functionality" do before do @client = Instagram::Client.new(client_id: "CID", client_secret: "CS") @url = @client.send(:connection).build_url("/oauth/access_token/").to_s stub_request(:post, @url) .with(body: { client_id: "CID", client_secret: "CS", redirect_uri: "http://localhost:4567/oauth/callback", grant_type: "authorization_code", code: "C" }) .to_return(status: 200, body: fixture("access_token.json"), headers: {}) end it "should get the correct resource" do @client.get_access_token(code = "C", redirect_uri: "http://localhost:4567/oauth/callback") expect(a_request(:post, @url) .with(body: { client_id: "CID", client_secret: "CS", redirect_uri: "http://localhost:4567/oauth/callback", grant_type: "authorization_code", code: "C" })) .to have_been_made end it "should return a hash with an access_token and user data" do response = @client.get_access_token(code = "C", redirect_uri: "http://localhost:4567/oauth/callback") expect(response.access_token).to eq("at") expect(response.user.username).to eq("mikeyk") end end describe "redirect_uri param" do before do @redirect_uri_config = "http://localhost:4567/oauth/callback_config" @client = Instagram::Client.new(client_id: "CID", client_secret: "CS", redirect_uri: @redirect_uri_config) @url = @client.send(:connection).build_url("/oauth/access_token/").to_s stub_request(:post, @url) end it "should fall back to configuration redirect_uri if not passed as option" do @client.get_access_token(code = "C") expect(a_request(:post, @url) .with(body: hash_including(redirect_uri: @redirect_uri_config))) .to have_been_made end it "should override configuration redirect_uri if passed as option" do redirect_uri_option = "http://localhost:4567/oauth/callback_option" @client.get_access_token(code = "C", redirect_uri: redirect_uri_option) expect(a_request(:post, @url) .with(body: hash_including(redirect_uri: redirect_uri_option))) .to have_been_made end end describe "loud_logger param" do before do @client = Instagram::Client.new(loud_logger: true) end context "outputs to STDOUT with faraday logs when enabled" do before do stub_get("users/self/feed.json") .to_return(body: fixture("user_media_feed.json"), headers: { content_type: "application/json; charset=utf-8" }) end it "should return the body error message" do output = capture_output do @client.user_media_feed end expect(output).to include "INFO -- : Started GET request to: https://api.instagram.com/v1/users/self/feed.json" expect(output).to include "DEBUG -- : Response Headers:" expect(output).to include "User-Agent : Instagram Ruby Gem #{Instagram::VERSION}" expect(output).to include "http://distillery.s3.amazonaws.com/media/2011/01/31/0f8e832c3dc6420bb6ddf0bd09f032f6_6.jpg" end end context "shows STDOUT output when errors occur" do before do stub_get("users/self/feed.json") .to_return(body: '{"meta":{"error_message": "Bad words are bad."}}', status: 400) end it "should return the body error message" do output = capture_output do begin @client.user_media_feed rescue nil end end expect(output).to include "INFO -- : Started GET request to: https://api.instagram.com/v1/users/self/feed.json" expect(output).to include "DEBUG -- : Response Headers:" expect(output).to include "User-Agent : Instagram Ruby Gem #{Instagram::VERSION}" expect(output).to include '{"meta":{"error_message": "Bad words are bad."}}' end end end end end