require File.join(File.dirname(__FILE__), 'spec_helper' ) describe "Itrigga::NetHelper" do before(:each) do @mock_response = mock("response") @mock_response.stub!(:body).and_return("body") end describe "typhoeus_present?" do context "when Typhoeus is loaded" do before(:each) do Itrigga::NetHelper.send(:const_set, "Typhoeus", Proc.new {}) end it "should return true" do Itrigga::NetHelper.typhoeus_present?.should == true end end context "when Typhoeus is not loaded" do before(:each) do Itrigga::NetHelper.send(:remove_const, "Typhoeus") end it "should return false" do Itrigga::NetHelper.typhoeus_present?.should == false end end end describe "do_get" do before(:each) do Itrigga::NetHelper.stub!(:typhoeus_present?).and_return(false) end it "should get the HTTP response" do Itrigga::NetHelper.stub!(:handle_response).and_return("") Net::HTTP.should_receive( :get_response ).with( URI.parse("http://some.com") ).and_return(@mock_response) Itrigga::NetHelper.do_get( "http://some.com" ) end it "should call handle_response with the response" do Net::HTTP.stub!( :get_response ).with( URI.parse("http://some.com") ).and_return(@mock_response) Itrigga::NetHelper.should_receive(:handle_response).and_return("") Itrigga::NetHelper.do_get( "http://some.com" ) end describe "when the GET takes longer than time_out seconds" do before(:each) do Itrigga::NetHelper.stub!(:get_with_timeout).and_raise( TimeoutError.new("expected timeout") ) end describe "when it has retried < retries_on_timeout times" do it "should retry" do Itrigga::NetHelper.should_receive(:get_with_timeout).exactly(3).times # NOTE: the important expectation is the above one! lambda { Itrigga::NetHelper.do_get( "http://some.com", 1, 2 ) }.should raise_error( IOError ) end end describe "when it has retried retries_on_timeout times" do it "should raise an IOError" do lambda { Itrigga::NetHelper.do_get( "http://some.com", 0, 2 ) }.should raise_error( IOError ) end end end end describe "handle_response" do describe "when the response is OK" do before(:each) do @mock_response.stub!(:is_a?).with(String).and_return false @mock_response.stub!(:is_a?).with(Net::HTTPSuccess).and_return true end it "should return the response body" do Itrigga::NetHelper.handle_response("http://some.com", @mock_response).should == "body" end end describe "when the response is a redirect" do before(:each) do @mock_response.stub!(:is_a?).with(String).and_return false @mock_response.stub!(:is_a?).with(Net::HTTPSuccess).and_return false @mock_response.stub!(:is_a?).with(Net::HTTPRedirection).and_return true @mock_response.stub!(:[]).with('location').and_return("http://some.redirect") end describe "when redirects > 0" do it "should recurse" do Itrigga::NetHelper.should_receive(:do_get) Itrigga::NetHelper.handle_response("http://some.com", @mock_response) end it "should pass the location field from the response as the url, and the same timeout" do Itrigga::NetHelper.should_receive(:do_get).with( "http://some.redirect", 23, anything ) Itrigga::NetHelper.handle_response( "http://some.com", @mock_response, 23) end it "should pass redirects - 1 as the redirects param" do Itrigga::NetHelper.should_receive(:do_get).with( anything, anything, 15 ) Itrigga::NetHelper.handle_response( "http://some.com", @mock_response, 23, 16) end describe "when the response location is relative" do before(:each) do @mock_response.stub!(:[]).with('location').and_return("/some/relative/path?param=567") end it "should pass on the absolute url" do Itrigga::NetHelper.should_receive(:do_get).with( "http://some.com/some/relative/path?param=567", anything, anything ) Itrigga::NetHelper.handle_response( "http://some.com/some_other/path.xml?id=123", @mock_response, 23, 16) end end end describe "when redirects = 0" do it "should raise an IOError" do lambda { Itrigga::NetHelper.handle_response( "http://some.com", @mock_response, 23, 0) }.should raise_error( IOError ) end end end end describe "query_string" do it "should return a string" do Itrigga::NetHelper.query_string( 'blart' => 'flange' ).should be_a(String) end it "should map the given hash to query string format" do Itrigga::NetHelper.query_string( 'blart'=>'flange').should == "blart=flange" end it "should sort the keys" do Itrigga::NetHelper.query_string( :c=>1, :b=>2, :a=>3 ).should == "a=3&b=2&c=1" end it "should join each key/value pair with an ampersand" do Itrigga::NetHelper.query_string( 'blart'=>'flange', 'donkey' => 'monkey').should == "blart=flange&donkey=monkey" end it "should transform sym keys to strings" do Itrigga::NetHelper.query_string( :blart=>'flange').should == "blart=flange" end it "should render nils as empty values" do Itrigga::NetHelper.query_string( 'blart'=>nil).should == "blart=" end describe "when :encode_values is true" do it "should url encode each value" do Itrigga::NetHelper.query_string( {'blart'=>'flange & more flange'}, :encode_values=>true ).should == "blart=flange%20%26%20more%20flange" end end describe "when :skip_empty is true" do it "should not include empty-valued fields" do Itrigga::NetHelper.query_string( {:c=>1, :b=>nil, :a=>''}, :skip_empty=>true ).should == "c=1" end end end describe "discover_favicon_url" do before(:each) do @url = "http://blart.com" Itrigga::NetHelper.stub!(:discover_icon_hrefs).with(@url).and_return([]) Itrigga::NetHelper.stub!(:get_with_timeout).and_return("") end it "should get the given url joined with favicon.ico" do Itrigga::NetHelper.should_receive(:get_with_timeout).with("http://blart.com/favicon.ico", anything).and_return("") Itrigga::NetHelper.discover_favicon_url("http://blart.com") end it "should call discover_icon_hrefs" do Itrigga::NetHelper.should_receive(:discover_icon_hrefs).with(@url).and_return([]) Itrigga::NetHelper.discover_favicon_url(@url) end context "each discovered href" do context "when the get is a success" do before(:each) do Itrigga::NetHelper.stub!(:discover_icon_hrefs).with(@url).and_return(["/some/bad/path.ico", "/some/good/path.ico"]) @mock_404 = mock("404"); @mock_200 = mock("200") @mock_404.stub!(:is_a?).with(Net::HTTPSuccess).and_return(false) @mock_200.stub!(:is_a?).with(Net::HTTPSuccess).and_return(true) Itrigga::NetHelper.stub!(:get_with_timeout).and_return( @mock_404, @mock_404, @mock_200 ) end it "should return the href joined onto the root url" do Itrigga::NetHelper.discover_favicon_url(@url).should == "http://blart.com/some/good/path.ico" end end end end describe "discover_icon_hrefs" do before(:each) do @html = <<-HTML HTML @url = "http://blart.com" @mock_doc = mock("hpricot doc") @mock_doc.stub!(:search).and_return([]) Itrigga::NetHelper.stub!(:open).with("http://blart.com").and_yield(@html) end it "should open the given url" do Itrigga::NetHelper.should_receive(:open).with("http://blart.com").and_yield(@html) Itrigga::NetHelper.discover_icon_hrefs(@url) end it "should parse the given url with hpricot" do Itrigga::NetHelper.should_receive(:parse_with_hpricot).with(@html).and_return(@mock_doc) Itrigga::NetHelper.discover_icon_hrefs(@url) end it "should search for links with a rel='shortcut icon'" do Itrigga::NetHelper.stub!(:parse_with_hpricot).with(@html).and_return(@mock_doc) @mock_doc.should_receive(:search).with("//link[@rel='shortcut icon']").and_return([]) Itrigga::NetHelper.discover_icon_hrefs(@url) end it "should search for links with a rel='icon'" do Itrigga::NetHelper.stub!(:parse_with_hpricot).with(@html).and_return(@mock_doc) @mock_doc.should_receive(:search).with("//link[@rel='shortcut icon']").and_return([]) Itrigga::NetHelper.discover_icon_hrefs(@url) end it "should return the collected href attributes" do Itrigga::NetHelper.discover_icon_hrefs(@url).should == ["http://an.absolute/url", "relative/url"] end end describe "raw_get" do before(:each) do Itrigga::NetHelper.stub!(:get_with_auth).and_return( 'body' ) Itrigga::NetHelper.stub!(:establish_session_if_needed) Itrigga::NetHelper.stub!(:typhoeus_present?).and_return(false) @mock_session = mock("http session") @mock_session.stub!(:request_get).and_return( @mock_response = mock('request_get response') ) @mock_response.stub!(:body).and_return('response body') @mock_parsed_url = mock("parsed url") @mock_parsed_url.stub!(:host).and_return("host") @mock_parsed_url.stub!(:path).and_return("path") @mock_parsed_url.stub!(:port).and_return("port") @mock_response = mock('response') @mock_response.stub!(:is_a?).with(Net::HTTPRedirection).and_return(false) @mock_response.stub!(:body).and_return('cheese') end it "should call establish_session_if_needed with the given opts" do Itrigga::NetHelper.should_receive(:establish_session_if_needed).with(hash_including(:blart=>'flange')) Itrigga::NetHelper.raw_get(:blart=>'flange', :http_session=>@mock_session, :parsed_url=>@mock_parsed_url) end context "when given a :username" do it "should call get_with_auth with the given options" do Itrigga::NetHelper.should_receive(:get_with_auth).with(hash_including(:username=>'dave')).and_return(@mock_response) Itrigga::NetHelper.raw_get(:username=>'dave') end it "should return the result of get_with_auth" do Itrigga::NetHelper.stub!(:get_with_auth).with(hash_including(:username=>'dave')).and_return(@mock_response) Itrigga::NetHelper.raw_get(:username=>'dave').should == 'cheese' end context "when response is a redirection" do before(:each) do @mock_response.stub!(:is_a?).with(Net::HTTPRedirection).and_return(true, false) @mock_response.stub!(:[]).with('location').and_return("http://cheesefish.com") URI.stub!(:parse).with("http://cheesefish.com").and_return(@mock_parsed_url = mock('parsed url')) end it "should follow the redirect" do URI.should_receive(:parse).with("http://cheesefish.com").and_return(@mock_parsed_url = mock('parsed url')) Itrigga::NetHelper.should_receive(:get_with_auth).twice.and_return(@mock_response) Itrigga::NetHelper.raw_get(:username=>'dave') end end end context "when not given a :username" do it "should call request_get on the http session with the :parsed_url's path and :headers" do @mock_session.should_receive(:request_get).with( 'path', {:donkey=>'dipstick'}).and_return(@mock_response) Itrigga::NetHelper.raw_get( :parsed_url=>@mock_parsed_url, :http_session=>@mock_session, :headers=>{:donkey=>'dipstick'} ) end it "should return the result of calling body on the request_get's response" do Itrigga::NetHelper.raw_get(:parsed_url=>@mock_parsed_url, :http_session=>@mock_session).should == 'response body' end end end describe "get_with_auth" do before(:each) do Itrigga::NetHelper.stub!(:establish_session_if_needed) Itrigga::NetHelper.stub!(:typhoeus_present).and_return(false) @mock_get = mock('get') @mock_get.stub!(:basic_auth) Net::HTTP::Get.stub!(:new).and_return(@mock_get) @mock_parsed_url = mock("parsed url") @mock_parsed_url.stub!(:host).and_return("host") @mock_parsed_url.stub!(:path).and_return("path") @mock_parsed_url.stub!(:port).and_return("port") @mock_session = mock("http session") @mock_session.stub!(:request).and_return("request response") end it "should call establish_session_if_needed with the given opts" do Itrigga::NetHelper.should_receive(:establish_session_if_needed).with(hash_including(:blart=>'flange')) Itrigga::NetHelper.get_with_auth(:blart=>'flange', :parsed_url=>@mock_parsed_url, :http_session=>@mock_session) end it "should create a new Net::HTTP::Get with the path of the :parsed_url" do Net::HTTP::Get.should_receive(:new).with('path').and_return(@mock_get) Itrigga::NetHelper.get_with_auth(:blart=>'flange', :parsed_url=>@mock_parsed_url, :http_session=>@mock_session) end it "should call basic_auth on the get, passing :username and :password from the given params" do @mock_get.should_receive(:basic_auth).with( 'username', 'password' ) Itrigga::NetHelper.get_with_auth(:username=>'username', :password=>'password', :parsed_url=>@mock_parsed_url, :http_session=>@mock_session) end it "should call request on the http_session with the get, and any given :headers" do @mock_session.should_receive(:request).with(@mock_get, {:header1=>'value1'}) Itrigga::NetHelper.get_with_auth(:http_session=>@mock_session, :headers=>{:header1=>'value1'}, :parsed_url=>@mock_parsed_url, :http_session=>@mock_session ) end it "should return the result of the request" do @mock_session.should_receive(:request).with(@mock_get, {:header1=>'value1'}).and_return("cheese") Itrigga::NetHelper.get_with_auth(:http_session=>@mock_session, :headers=>{:header1=>'value1'}, :parsed_url=>@mock_parsed_url, :http_session=>@mock_session ).should == "cheese" end end describe "establish_session_if_needed" do before(:each) do @mock_parsed_url = mock("parsed url") @mock_parsed_url.stub!(:host).and_return("host") @mock_parsed_url.stub!(:port).and_return("port") @mock_parsed_url.stub!(:scheme).and_return("scheme") @mock_session = mock('http session') @mock_session.stub!(:use_ssl=) Net::HTTP.stub!(:new).and_return(@mock_session) end context "When not given a :parsed_url" do it "should set :parsed_url to URI.parse(:url)" do URI.should_receive(:parse).with("URL").and_return(@mock_parsed_url) Itrigga::NetHelper.establish_session_if_needed(:url=>"URL") end end context "When not given a :http_session" do it "should set :http_session to a new Net::HTTP with the parsed_url's host and port" do Net::HTTP.should_receive(:new).with("host", "port").and_return(@mock_session) Itrigga::NetHelper.establish_session_if_needed(:parsed_url=>@mock_parsed_url) end end context "when the :parsed_url's scheme is https" do before(:each) do @mock_parsed_url.stub!(:scheme).and_return("https") end it "should set use_ssl=true on the http session" do @mock_session.should_receive(:use_ssl=).with(true) Itrigga::NetHelper.establish_session_if_needed(:parsed_url=>@mock_parsed_url) end end end describe "shorten_url" do before do @raw_url = "http://very_long_url_goes_here.com" @shortened_url = "http://url_goes_here.com" Itrigga::NetHelper.stub!(:format_url_shortener_api_url).and_return("http://myshorturl.com") Itrigga::NetHelper.stub!(:get).and_return("{\"status_code\":200,\"data\":{\"url\":\"#{@shortened_url}\"}}") end describe "with valid input" do it "should call format_url_shortener_api_url with the given url and config" do Itrigga::NetHelper.should_receive(:format_url_shortener_api_url).with(@raw_url, {:blart=>'flange'}) Itrigga::NetHelper.shorten_url(:url=>@raw_url, :config=>{:blart=>'flange'}) end it "should return a short url" do Itrigga::NetHelper.shorten_url(:url=>@raw_url).should == @shortened_url end it "should return raw_url on web request timesout" do Itrigga::NetHelper.stub!(:get).and_raise(Exception) Itrigga::NetHelper.shorten_url(:url=>@raw_url).should == @raw_url end it "should return raw url for anything other than a status 200" do Itrigga::NetHelper.stub!(:get).and_return("{\"status_code\":500,\"data\":{\"url\":\"#{@shortened_url}\"}}") Itrigga::NetHelper.shorten_url(:url=>@raw_url).should == @raw_url end end end describe "format_url_shortener_api_url" do before do @raw_url = "http://very_long_url_goes_here.com" @config_hash = ( {:url => "{{raw_url}}", :username => "a", :api_key => "123"} ) end it "should return the api url" do Itrigga::NetHelper.format_url_shortener_api_url(@raw_url, @config_hash).should == "http%3A%2F%2Fvery_long_url_goes_here.com" end it "should url encode the raw_url" do CGI.should_receive(:escape).with(@raw_url).and_return("http%3A%2F%2Fvery_long_url_goes_here.com") Itrigga::NetHelper.format_url_shortener_api_url(@raw_url, @config_hash) end end describe "transfer_file_scp" do before(:each) do @host = { :display_name => "display_name", :port => 123, :user => "user", :host => "hostname", :ssh_key_path => "key_file_path" } Itrigga::NetHelper.stub!(:'`').and_return(true) File.stub!(:exist?).and_return(true) end it "should raise error if no file in opts" do lambda { Itrigga::NetHelper.transfer_file_scp(:host=>@host) }.should raise_error(ArgumentError) end it "should raise error if file in opts does not exist" do File.stub!(:exist?).and_return(false) lambda { Itrigga::NetHelper.transfer_file_scp(:file => "mycrazyfile", :host=>@host) }.should raise_error(ArgumentError) end it "should raise error if no host in opts" do lambda { Itrigga::NetHelper.transfer_file_scp(:file => "mycrazyfile") }.should raise_error(ArgumentError) end it "should raise error if no target_path in opts" do lambda { Itrigga::NetHelper.transfer_file_scp(:file => "mycrazyfile", :host=>@host) }.should raise_error(ArgumentError) end it "should not raise an error if the host exists" do lambda { Itrigga::NetHelper.transfer_file_scp(:file => "mycrazyfile", :host=>@host, :target_path => "/path/goes/here/to/file.xml")}.should_not raise_error end it "should call ssh to create dir path with the correct string" do opts = {:target => "display_name", :file => "a_file_name", :target_path => "/path/goes/here/to/file.xml", :host=>@host} Itrigga::NetHelper.should_receive(:'`').with("ssh -p123 -i key_file_path user@hostname 'mkdir -p /path/goes/here/to'") Itrigga::NetHelper.transfer_file_scp(opts) end it "should call scp with the correct string" do opts = {:target => "display_name", :file => "a_file_name", :target_path => "/path/goes/here/to/file.xml", :host=>@host} Itrigga::NetHelper.should_receive(:'`').with("scp -P123 -i key_file_path a_file_name user@hostname:/path/goes/here/to/file.xml") Itrigga::NetHelper.transfer_file_scp(opts) end end end