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| api.send(key).should == 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| api.send(key).should == @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| api.send(key).should == @configuration[key] end end describe "#connection" do it "should use the connection_options" do Faraday::Connection.should_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 subject.config.should == 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 url2.should == 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) url.should_not 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) url.should 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) url.should_not 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() url.should =~ /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) url.should =~ /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") 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"}). should 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") response.access_token.should == "at" response.user.username.should == "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") a_request(:post, @url). with(:body => hash_including({:redirect_uri => @redirect_uri_config})). should 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) a_request(:post, @url). with(:body => hash_including({:redirect_uri => redirect_uri_option})). should 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 @client.user_media_feed() rescue nil 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 context "will redact API keys if INSTAGRAM_GEM_REDACT=true" 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 redact API keys" do ENV.stub(:[]).with('http_proxy').and_return(nil) ENV.stub(:[]).with('INSTAGRAM_GEM_REDACT').and_return('true') 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' expect(output).to include 'access_token=[ACCESS-TOKEN]' end end end end end