require File.join(File.dirname(__FILE__), 'spec_helper' ) describe "Itrigga::NetHelper" do before do @default_http_params = { :timeout => 5, :retries_on_timeout => 5, :max_redirects => 3 } end describe "available_http_engines" do it "should return the constants defined in the Itrigga::NetHelper module (ie the classes)" do Itrigga::NetHelper.should_receive(:constants) Itrigga::NetHelper.available_http_engines end it "should return the correct classes" do Itrigga::NetHelper.available_http_engines.sort.should == ["RestClient","Typhoeus"].sort end end describe "default_http_engine" do it "should be rest client" do Itrigga::NetHelper.default_http_engine.should == "RestClient" end end describe "do_get" do before do Itrigga::NetHelper.stub!(:get).and_return("result") end context "using defaults" do it "should call get changing the params into a hash" do Itrigga::NetHelper.should_receive(:get).with(hash_including({:url => "blart"}.merge(@default_http_params))) Itrigga::NetHelper.do_get "blart" end end context "overriding defaults" do it "should call get changing the params into a hash" do Itrigga::NetHelper.should_receive(:get).with(hash_including(:url => "blart",:timeout => 1, :retries_on_timeout => 2, :max_redirects => 42)) Itrigga::NetHelper.do_get "blart", 1, 2, 42 end end it "should return the result from get" do Itrigga::NetHelper.do_get("blart").should == "result" end end describe "get" do before do Itrigga::NetHelper.stub!(:get_engine).and_return(@engine = mock("HTTPEngine")) @engine.stub!(:get).and_return("result") Itrigga::NetHelper.stub!(:with_timeout).and_yield @default_http_params = @default_http_params.merge({:headers => {}}) @default_http_params_with_url = {:url => "blart"}.merge(@default_http_params) end it "should raise error if no :url option given" do lambda { Itrigga::NetHelper.get }.should raise_error(ArgumentError,":url is required") end it "should call get_engine with merged params" do Itrigga::NetHelper.should_receive(:get_engine).with(hash_including(@default_http_params_with_url)) Itrigga::NetHelper.get :url => "blart" end it "should call with_timeout" do Itrigga::NetHelper.should_receive(:with_timeout).with(@default_http_params_with_url).and_yield Itrigga::NetHelper.get :url => "blart" end it "should call get in the http engine in the block" do @engine.should_receive(:get).with(@default_http_params_with_url).and_return("result") Itrigga::NetHelper.get :url => "blart" end it "should return the result of the block" do Itrigga::NetHelper.get(:url => "blart").should == "result" end end describe "with_timeout" do before do @block = Proc.new{ 6 + 6 } end context "when SystemTimer is available" do before do silence_warnings { Object.const_set(:SystemTimer, @system_timer = mock("SystemTimer")) } @system_timer.stub!(:timeout_after).and_yield end after do silence_warnings { Object.send(:remove_const, :SystemTimer) } end it "should call timeout_after" do @system_timer.should_receive(:timeout_after).with(42).and_yield Itrigga::NetHelper.with_timeout({:timeout => 42}, &@block) end it "should return the result from the block" do Itrigga::NetHelper.with_timeout({:timeout => 42}, &@block).should == 12 end it "should not call timeout" do Itrigga::NetHelper.should_not_receive(:timeout) Itrigga::NetHelper.with_timeout({:timeout => 42}, &@block) end end context "when SystemTimer is not available" do it "should call timeout" do Itrigga::NetHelper.should_receive(:timeout).with(42).and_yield Itrigga::NetHelper.with_timeout({:timeout => 42}, &@block) end it "should return the result from the block" do Itrigga::NetHelper.with_timeout({:timeout => 42}, &@block).should == 12 end end context "when an error is thrown" do it "should retry 3 times then raise an IOError" do Itrigga::NetHelper.should_receive(:timeout).exactly(4).times.and_raise(TimeoutError) lambda { Itrigga::NetHelper.with_timeout({:timeout => 42, :retries_on_timeout => 3}, &@block) }.should raise_error(IOError) end it "should not handle other errors" do Itrigga::NetHelper.stub!(:timeout).and_raise "Funkiness Alert!" lambda { Itrigga::NetHelper.with_timeout({:timeout => 42, :retries_on_timeout => 3}, &@block) }.should raise_error end end end describe "get_engine" do context "when the ITNH_HTTP_ENGINE is defined" do before do silence_warnings { Object.const_set(:ITNH_HTTP_ENGINE, "Typhoeus") Object.const_set(:Typhoeus, "Typhoeus") } end after do silence_warnings { Object.send(:remove_const, :ITNH_HTTP_ENGINE) Object.send(:remove_const, :Typhoeus) } end it "should return the Typhoeus class" do Itrigga::NetHelper.get_engine.should == Itrigga::NetHelper::Typhoeus end it "should respect overrides" do Itrigga::NetHelper.get_engine(:http_engine => "RestClient").should == Itrigga::NetHelper::RestClient end end context "with no Typhoeus defined" do it "should not use Typhoeus even when told to" do Object.send(:remove_const, :Typhoeus) rescue nil #only remove it if its present Itrigga::NetHelper.get_engine(:http_engine => "Typhoeus").should == Itrigga::NetHelper::RestClient # because Typhoeus is not defined (ie not available) end end it "should use the default engine if given an invalid option" do Itrigga::NetHelper.get_engine(:http_engine => "blart and flange").should == Itrigga::NetHelper::RestClient 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 "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 describe "ip_of" do before do IPSocket.stub!(:getaddress).and_return("ip_address") end it "should call getaddress" do IPSocket.should_receive(:getaddress).with("server").and_return("ip_address") Itrigga::NetHelper.ip_of("server") end it "should return the address" do Itrigga::NetHelper.ip_of("server").should == "ip_address" end end end