require File.dirname(__FILE__) + '/../spec_helper'
class Hell < StandardError; end
class FailParser
def self.parse(_, &on_failure)
on_failure.call
end
end
describe Feedzirra::Feed do
describe "#add_common_feed_element" do
before(:all) do
Feedzirra::Feed.add_common_feed_element("generator")
end
it "should parse the added element out of Atom feeds" do
Feedzirra::Feed.parse(sample_wfw_feed).generator.should == "TypePad"
end
it "should parse the added element out of Atom Feedburner feeds" do
Feedzirra::Parser::Atom.new.should respond_to(:generator)
end
it "should parse the added element out of RSS feeds" do
Feedzirra::Parser::RSS.new.should respond_to(:generator)
end
end
describe "#add_common_feed_entry_element" do
before(:all) do
Feedzirra::Feed.add_common_feed_entry_element("wfw:commentRss", :as => :comment_rss)
end
it "should parse the added element out of Atom feeds entries" do
Feedzirra::Feed.parse(sample_wfw_feed).entries.first.comment_rss.should == "this is the new val"
end
it "should parse the added element out of Atom Feedburner feeds entries" do
Feedzirra::Parser::AtomEntry.new.should respond_to(:comment_rss)
end
it "should parse the added element out of RSS feeds entries" do
Feedzirra::Parser::RSSEntry.new.should respond_to(:comment_rss)
end
end
describe '#parse_with' do
let(:xml) { '' }
it 'invokes the parser and passes the xml' do
parser = double 'Parser', parse: nil
parser.should_receive(:parse).with xml
Feedzirra::Feed.parse_with parser, xml
end
context 'with a callback block' do
it 'passes the callback to the parser' do
callback = -> { raise Hell }
expect do
Feedzirra::Feed.parse_with FailParser, xml, &callback
end.to raise_error Hell
end
end
end
describe "#parse" do # many of these tests are redundant with the specific feed type tests, but I put them here for completeness
context "when there's an available parser" do
it "should parse an rdf feed" do
feed = Feedzirra::Feed.parse(sample_rdf_feed)
feed.title.should == "HREF Considered Harmful"
feed.entries.first.published.should == Time.parse_safely("Tue Sep 02 19:50:07 UTC 2008")
feed.entries.size.should == 10
end
it "should parse an rss feed" do
feed = Feedzirra::Feed.parse(sample_rss_feed)
feed.title.should == "Tender Lovemaking"
feed.entries.first.published.should == Time.parse_safely("Thu Dec 04 17:17:49 UTC 2008")
feed.entries.size.should == 10
end
it "should parse an atom feed" do
feed = Feedzirra::Feed.parse(sample_atom_feed)
feed.title.should == "Amazon Web Services Blog"
feed.entries.first.published.should == Time.parse_safely("Fri Jan 16 18:21:00 UTC 2009")
feed.entries.size.should == 10
end
it "should parse an feedburner atom feed" do
feed = Feedzirra::Feed.parse(sample_feedburner_atom_feed)
feed.title.should == "Paul Dix Explains Nothing"
feed.entries.first.published.should == Time.parse_safely("Thu Jan 22 15:50:22 UTC 2009")
feed.entries.size.should == 5
end
it "should parse an itunes feed" do
feed = Feedzirra::Feed.parse(sample_itunes_feed)
feed.title.should == "All About Everything"
feed.entries.first.published.should == Time.parse_safely("Wed, 15 Jun 2005 19:00:00 GMT")
feed.entries.size.should == 3
end
end
context "when there's no available parser" do
it "raises Feedzirra::NoParserAvailable" do
proc {
Feedzirra::Feed.parse("I'm an invalid feed")
}.should raise_error(Feedzirra::NoParserAvailable)
end
end
it "should parse an feedburner rss feed" do
feed = Feedzirra::Feed.parse(sample_rss_feed_burner_feed)
feed.title.should == "TechCrunch"
feed.entries.first.published.should == Time.parse_safely("Wed Nov 02 17:25:27 UTC 2011")
feed.entries.size.should == 20
end
end
describe "#determine_feed_parser_for_xml" do
it 'should return the Feedzirra::Parser::GoogleDocsAtom calss for a Google Docs atom feed' do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_google_docs_list_feed).should == Feedzirra::Parser::GoogleDocsAtom
end
it "should return the Feedzirra::Parser::Atom class for an atom feed" do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_atom_feed).should == Feedzirra::Parser::Atom
end
it "should return the Feedzirra::Parser::AtomFeedBurner class for an atom feedburner feed" do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_feedburner_atom_feed).should == Feedzirra::Parser::AtomFeedBurner
end
it "should return the Feedzirra::Parser::RSS class for an rdf/rss 1.0 feed" do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rdf_feed).should == Feedzirra::Parser::RSS
end
it "should return the Feedzirra::Parser::RSSFeedBurner class for an rss feedburner feed" do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed_burner_feed).should == Feedzirra::Parser::RSSFeedBurner
end
it "should return the Feedzirra::Parser::RSS object for an rss 2.0 feed" do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed).should == Feedzirra::Parser::RSS
end
it "should return a Feedzirra::Parser::RSS object for an itunes feed" do
Feedzirra::Feed.determine_feed_parser_for_xml(sample_itunes_feed).should == Feedzirra::Parser::ITunesRSS
end
end
describe "#setup_easy" do
class MockCurl
attr_accessor :follow_location, :userpwd, :proxy_url, :proxy_port, :max_redirects, :timeout, :ssl_verify_host, :ssl_verify_peer, :ssl_version, :enable_cookies, :cookiefile, :cookies
def headers
@headers ||= {}
end
end
let(:curl) { MockCurl.new }
it "sets defaults on curl" do
Feedzirra::Feed.setup_easy curl
curl.headers["User-Agent"].should eq Feedzirra::Feed::USER_AGENT
curl.follow_location.should eq true
end
it "allows user agent over-ride" do
Feedzirra::Feed.setup_easy(curl, user_agent: '007')
curl.headers["User-Agent"].should eq '007'
end
it "enables compression" do
Feedzirra::Feed.setup_easy(curl, compress: true)
curl.headers["Accept-encoding"].should eq 'gzip, deflate'
end
it "enables compression even when you act like you don't want it" do
Feedzirra::Feed.setup_easy(curl, compress: false)
curl.headers["Accept-encoding"].should eq 'gzip, deflate'
end
it "sets up http auth" do
Feedzirra::Feed.setup_easy(curl, http_authentication: ['user', 'pass'])
curl.userpwd.should eq 'user:pass'
end
it "passes known options to curl" do
known_options = {
enable_cookies: true,
cookiefile: 'cookies.txt',
cookies: 'asdf',
proxy_url: 'http://proxy.url.com',
proxy_port: '1234',
max_redirects: 2,
timeout: 500,
ssl_verify_host: true,
ssl_verify_peer: true,
ssl_version: :omg
}
Feedzirra::Feed.setup_easy curl, known_options
known_options.each do |option|
key, value = option
curl.send(key).should eq value
end
end
it "ignores unknown options" do
expect { Feedzirra::Feed.setup_easy curl, foo: :bar }.to_not raise_error
end
end
describe "when adding feed types" do
it "should prioritize added types over the built in ones" do
feed_text = "Atom asdf"
Feedzirra::Parser::Atom.stub(:able_to_parse?).and_return(true)
new_feed_type = Class.new do
def self.able_to_parse?(val)
true
end
end
new_feed_type.should be_able_to_parse(feed_text)
Feedzirra::Feed.add_feed_class(new_feed_type)
Feedzirra::Feed.determine_feed_parser_for_xml(feed_text).should == new_feed_type
# this is a hack so that this doesn't break the rest of the tests
Feedzirra::Feed.feed_classes.reject! {|o| o == new_feed_type }
end
end
describe '#etag_from_header' do
before(:each) do
@header = "HTTP/1.0 200 OK\r\nDate: Thu, 29 Jan 2009 03:55:24 GMT\r\nServer: Apache\r\nX-FB-Host: chi-write6\r\nLast-Modified: Wed, 28 Jan 2009 04:10:32 GMT\r\nETag: ziEyTl4q9GH04BR4jgkImd0GvSE\r\nP3P: CP=\"ALL DSP COR NID CUR OUR NOR\"\r\nConnection: close\r\nContent-Type: text/xml;charset=utf-8\r\n\r\n"
end
it "should return the etag from the header if it exists" do
Feedzirra::Feed.etag_from_header(@header).should == "ziEyTl4q9GH04BR4jgkImd0GvSE"
end
it "should return nil if there is no etag in the header" do
Feedzirra::Feed.etag_from_header("foo").should be_nil
end
end
describe '#last_modified_from_header' do
before(:each) do
@header = "HTTP/1.0 200 OK\r\nDate: Thu, 29 Jan 2009 03:55:24 GMT\r\nServer: Apache\r\nX-FB-Host: chi-write6\r\nLast-Modified: Wed, 28 Jan 2009 04:10:32 GMT\r\nETag: ziEyTl4q9GH04BR4jgkImd0GvSE\r\nP3P: CP=\"ALL DSP COR NID CUR OUR NOR\"\r\nConnection: close\r\nContent-Type: text/xml;charset=utf-8\r\n\r\n"
end
it "should return the last modified date from the header if it exists" do
Feedzirra::Feed.last_modified_from_header(@header).should == Time.parse_safely("Wed, 28 Jan 2009 04:10:32 GMT")
end
it "should return nil if there is no last modified date in the header" do
Feedzirra::Feed.last_modified_from_header("foo").should be_nil
end
end
describe "fetching feeds" do
before(:each) do
@paul_feed = { :xml => load_sample("PaulDixExplainsNothing.xml"), :url => "http://feeds.feedburner.com/PaulDixExplainsNothing" }
@trotter_feed = { :xml => load_sample("TrotterCashionHome.xml"), :url => "http://feeds2.feedburner.com/trottercashion" }
end
describe "#fetch_raw" do
before(:each) do
@cmock = double('cmock', :header_str => '', :body_str => @paul_feed[:xml] )
@multi = double('curl_multi', :add => true, :perform => true)
@curl_easy = double('curl_easy')
@curl = double('curl', :headers => {}, :follow_location= => true, :on_failure => true, :on_complete => true)
@curl.stub(:on_success).and_yield(@cmock)
Curl::Multi.stub(:new).and_return(@multi)
Curl::Easy.stub(:new).and_yield(@curl).and_return(@curl_easy)
end
it "should set user agent if it's passed as an option" do
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :user_agent => 'Custom Useragent')
@curl.headers['User-Agent'].should == 'Custom Useragent'
end
it "should set user agent to default if it's not passed as an option" do
Feedzirra::Feed.fetch_raw(@paul_feed[:url])
@curl.headers['User-Agent'].should == Feedzirra::Feed::USER_AGENT
end
it "should set if modified since as an option if passed" do
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :if_modified_since => Time.parse_safely("Wed, 28 Jan 2009 04:10:32 GMT"))
@curl.headers["If-Modified-Since"].should == 'Wed, 28 Jan 2009 04:10:32 GMT'
end
it "should set if none match as an option if passed" do
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :if_none_match => 'ziEyTl4q9GH04BR4jgkImd0GvSE')
@curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
end
it 'should set userpwd for http basic authentication if :http_authentication is passed' do
@curl.should_receive(:userpwd=).with('username:password')
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :http_authentication => ['username', 'password'])
end
it 'should set accepted encodings' do
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :compress => true)
@curl.headers["Accept-encoding"].should == 'gzip, deflate'
end
it "should return raw xml" do
Feedzirra::Feed.fetch_raw(@paul_feed[:url]).should =~ /^#{Regexp.escape('')}/
end
it "should take multiple feed urls and return a hash of urls and response xml" do
multi = double('curl_multi', :add => true, :perform => true)
Curl::Multi.stub(:new).and_return(multi)
paul_response = double('paul_response', :header_str => '', :body_str => @paul_feed[:xml] )
trotter_response = double('trotter_response', :header_str => '', :body_str => @trotter_feed[:xml] )
paul_curl = double('paul_curl', :headers => {}, :follow_location= => true, :on_failure => true, :on_complete => true)
paul_curl.stub(:on_success).and_yield(paul_response)
trotter_curl = double('trotter_curl', :headers => {}, :follow_location= => true, :on_failure => true, :on_complete => true)
trotter_curl.stub(:on_success).and_yield(trotter_response)
Curl::Easy.should_receive(:new).with(@paul_feed[:url]).ordered.and_yield(paul_curl)
Curl::Easy.should_receive(:new).with(@trotter_feed[:url]).ordered.and_yield(trotter_curl)
results = Feedzirra::Feed.fetch_raw([@paul_feed[:url], @trotter_feed[:url]])
results.keys.should include(@paul_feed[:url])
results.keys.should include(@trotter_feed[:url])
results[@paul_feed[:url]].should =~ /Paul Dix/
results[@trotter_feed[:url]].should =~ /Trotter Cashion/
end
it "should always return a hash when passed an array" do
results = Feedzirra::Feed.fetch_raw([@paul_feed[:url]])
results.class.should == Hash
end
end
describe "#add_url_to_multi" do
before(:each) do
allow_message_expectations_on_nil
@multi = Curl::Multi.get([@paul_feed[:url]], {:follow_location => true}, {:pipeline => true})
@multi.stub(:add)
@easy_curl = Curl::Easy.new(@paul_feed[:url])
Curl::Easy.should_receive(:new).and_yield(@easy_curl)
end
it "should set user agent if it's passed as an option" do
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :user_agent => 'My cool application')
@easy_curl.headers["User-Agent"].should == 'My cool application'
end
it "should set user agent to default if it's not passed as an option" do
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.headers["User-Agent"].should == Feedzirra::Feed::USER_AGENT
end
it "should set if modified since as an option if passed" do
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :if_modified_since => Time.parse_safely("Jan 25 2009 04:10:32 GMT"))
@easy_curl.headers["If-Modified-Since"].should == 'Sun, 25 Jan 2009 04:10:32 GMT'
end
it 'should set follow location to true' do
@easy_curl.should_receive(:follow_location=).with(true)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
end
it 'should set userpwd for http basic authentication if :http_authentication is passed' do
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :http_authentication => ['myusername', 'mypassword'])
@easy_curl.userpwd.should == 'myusername:mypassword'
end
it 'should set accepted encodings' do
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {:compress => true})
@easy_curl.headers["Accept-encoding"].should == 'gzip, deflate'
end
it "should set if_none_match as an option if passed" do
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :if_none_match => 'ziEyTl4q9GH04BR4jgkImd0GvSE')
@easy_curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
end
describe 'on success' do
before(:each) do
@feed = double('feed', :feed_url= => true, :etag= => true, :last_modified= => true)
Feedzirra::Feed.stub(:decode_content).and_return(@paul_feed[:xml])
Feedzirra::Feed.stub(:determine_feed_parser_for_xml).and_return(Feedzirra::Parser::AtomFeedBurner)
Feedzirra::Parser::AtomFeedBurner.stub(:parse).and_return(@feed)
Feedzirra::Feed.stub(:etag_from_header).and_return('ziEyTl4q9GH04BR4jgkImd0GvSE')
Feedzirra::Feed.stub(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
end
it 'should decode the response body' do
Feedzirra::Feed.should_receive(:decode_content).with(@easy_curl).and_return(@paul_feed[:xml])
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should determine the xml parser class' do
Feedzirra::Feed.should_receive(:determine_feed_parser_for_xml).with(@paul_feed[:xml]).and_return(Feedzirra::Parser::AtomFeedBurner)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should parse the xml' do
Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).
with(@paul_feed[:xml]).and_return(@feed)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
describe 'when a compatible xml parser class is found' do
it 'should set the last effective url to the feed url' do
@easy_curl.should_receive(:last_effective_url).and_return(@paul_feed[:url])
@feed.should_receive(:feed_url=).with(@paul_feed[:url])
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should set the etags on the feed' do
@feed.should_receive(:etag=).with('ziEyTl4q9GH04BR4jgkImd0GvSE')
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should set the last modified on the feed' do
@feed.should_receive(:last_modified=).with('Wed, 28 Jan 2009 04:10:32 GMT')
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should add the feed to the responses' do
responses = {}
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
@easy_curl.on_success.call(@easy_curl)
responses.length.should == 1
responses['http://feeds.feedburner.com/PaulDixExplainsNothing'].should == @feed
end
it 'should call proc if :on_success option is passed' do
success = lambda { |url, feed| }
success.should_receive(:call).with(@paul_feed[:url], @feed)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_success => success })
@easy_curl.on_success.call(@easy_curl)
end
describe 'when the parser raises an exception' do
it 'invokes the on_failure callback' do
failure = lambda { |url, feed| }
failure.should_receive(:call).with(@paul_feed[:url], 0, nil, nil)
Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).and_raise Exception
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { on_failure: failure })
@easy_curl.on_success.call(@easy_curl)
end
end
describe 'when the parser invokes its on_failure callback' do
before(:each) do
Feedzirra::Feed.stub(:determine_feed_parser_for_xml).and_return FailParser
end
it 'invokes the on_failure callback' do
failure = lambda { |url, feed| }
failure.should_receive(:call).with(@paul_feed[:url], 0, nil, nil)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { on_failure: failure })
@easy_curl.on_success.call(@easy_curl)
end
end
end
describe 'when no compatible xml parser class is found' do
it 'invokes the on_failure callback' do
failure = lambda { |url, feed| }
failure.should_receive(:call).with(@paul_feed[:url], 0, nil, nil)
Feedzirra::Feed.should_receive(:determine_feed_parser_for_xml).and_return nil
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { on_failure: failure })
@easy_curl.on_success.call(@easy_curl)
end
end
end
describe 'on failure' do
before(:each) do
@headers = "HTTP/1.0 500 Something Bad\r\nDate: Thu, 29 Jan 2009 03:55:24 GMT\r\nServer: Apache\r\nX-FB-Host: chi-write6\r\nLast-Modified: Wed, 28 Jan 2009 04:10:32 GMT\r\n"
@body = 'Sorry, something broke'
@easy_curl.stub(:response_code).and_return(500)
@easy_curl.stub(:header_str).and_return(@headers)
@easy_curl.stub(:body_str).and_return(@body)
end
it 'should call proc if :on_failure option is passed' do
failure = lambda { |url, feed| }
failure.should_receive(:call).with(@paul_feed[:url], 500, @headers, @body)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_failure => failure })
@easy_curl.on_failure.call(@easy_curl)
end
it 'should return the http code in the responses' do
responses = {}
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
@easy_curl.on_failure.call(@easy_curl)
responses.length.should == 1
responses[@paul_feed[:url]].should == 500
end
end
describe 'on complete for 404s' do
before(:each) do
@headers = "HTTP/1.0 404 Not Found\r\nDate: Thu, 29 Jan 2009 03:55:24 GMT\r\nServer: Apache\r\nX-FB-Host: chi-write6\r\nLast-Modified: Wed, 28 Jan 2009 04:10:32 GMT\r\n"
@body = 'Page could not be found.'
@easy_curl.stub(:response_code).and_return(404)
@easy_curl.stub(:header_str).and_return(@headers)
@easy_curl.stub(:body_str).and_return(@body)
end
it 'should call proc if :on_failure option is passed' do
complete = lambda { |url| }
complete.should_receive(:call).with(@paul_feed[:url], 404, @headers, @body)
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_failure => complete })
@easy_curl.on_missing.call(@easy_curl)
end
it 'should return the http code in the responses' do
responses = {}
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
@easy_curl.on_complete.call(@easy_curl)
responses.length.should == 1
responses[@paul_feed[:url]].should == 404
end
end
end
describe "#add_feed_to_multi" do
before(:each) do
allow_message_expectations_on_nil
@multi = Curl::Multi.get([@paul_feed[:url]], {:follow_location => true}, {:pipeline => true})
@multi.stub(:add)
@easy_curl = Curl::Easy.new(@paul_feed[:url])
@feed = Feedzirra::Feed.parse(sample_feedburner_atom_feed)
Curl::Easy.should_receive(:new).and_yield(@easy_curl)
end
it "should set user agent if it's passed as an option" do
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, :user_agent => 'My cool application')
@easy_curl.headers["User-Agent"].should == 'My cool application'
end
it "should set user agent to default if it's not passed as an option" do
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.headers["User-Agent"].should == Feedzirra::Feed::USER_AGENT
end
it "should set if modified since as an option if passed" do
modified_time = Time.parse_safely("Wed, 28 Jan 2009 04:10:32 GMT")
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {:if_modified_since => modified_time})
modified_time.should be > @feed.last_modified
@easy_curl.headers["If-Modified-Since"].should == modified_time
end
it 'should set follow location to true' do
@easy_curl.should_receive(:follow_location=).with(true)
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
end
it 'should set userpwd for http basic authentication if :http_authentication is passed' do
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, :http_authentication => ['myusername', 'mypassword'])
@easy_curl.userpwd.should == 'myusername:mypassword'
end
it "should set if_none_match as an option if passed" do
@feed.etag = 'ziEyTl4q9GH04BR4jgkImd0GvSE'
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
end
describe 'on success' do
before(:each) do
@new_feed = @feed.clone
@feed.stub(:update_from_feed)
Feedzirra::Feed.stub(:decode_content).and_return(@paul_feed[:xml])
Feedzirra::Feed.stub(:determine_feed_parser_for_xml).and_return(Feedzirra::Parser::AtomFeedBurner)
Feedzirra::Parser::AtomFeedBurner.stub(:parse).and_return(@new_feed)
Feedzirra::Feed.stub(:etag_from_header).and_return('ziEyTl4q9GH04BR4jgkImd0GvSE')
Feedzirra::Feed.stub(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
end
it 'should parse the updated feed' do
Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).and_return(@new_feed)
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should set the last effective url to the feed url' do
@easy_curl.should_receive(:last_effective_url).and_return(@paul_feed[:url])
@new_feed.should_receive(:feed_url=).with(@paul_feed[:url])
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should set the etags on the feed' do
@new_feed.should_receive(:etag=).with('ziEyTl4q9GH04BR4jgkImd0GvSE')
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should set the last modified on the feed' do
@new_feed.should_receive(:last_modified=).with('Wed, 28 Jan 2009 04:10:32 GMT')
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
it 'should add the feed to the responses' do
responses = {}
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], responses, {})
@easy_curl.on_success.call(@easy_curl)
responses.length.should == 1
responses['http://feeds.feedburner.com/PaulDixExplainsNothing'].should == @feed
end
it 'should call proc if :on_success option is passed' do
success = lambda { |feed| }
success.should_receive(:call).with(@feed)
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
@easy_curl.on_success.call(@easy_curl)
end
it 'should call update from feed on the old feed with the updated feed' do
@feed.should_receive(:update_from_feed).with(@new_feed)
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
@easy_curl.on_success.call(@easy_curl)
end
describe 'when the parser invokes its on_failure callback' do
before(:each) do
Feedzirra::Feed.stub(:determine_feed_parser_for_xml).and_return FailParser
end
it 'invokes the on_failure callback' do
failure = lambda { |feed| }
failure.should_receive(:call)
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { on_failure: failure })
@easy_curl.on_success.call(@easy_curl)
end
end
end
describe 'on failure' do
before(:each) do
@headers = "HTTP/1.0 404 Not Found\r\nDate: Thu, 29 Jan 2009 03:55:24 GMT\r\nServer: Apache\r\nX-FB-Host: chi-write6\r\nLast-Modified: Wed, 28 Jan 2009 04:10:32 GMT\r\n"
@body = 'Page could not be found.'
@easy_curl.stub(:response_code).and_return(404)
@easy_curl.stub(:header_str).and_return(@headers)
@easy_curl.stub(:body_str).and_return(@body)
end
it 'should call on success callback if the response code is 304' do
success = lambda { |feed| }
success.should_receive(:call).with(@feed)
@easy_curl.should_receive(:response_code).and_return(304)
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
@easy_curl.on_redirect.call(@easy_curl)
end
it 'should return the http code in the responses' do
responses = {}
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], responses, {})
@easy_curl.on_failure.call(@easy_curl)
responses.length.should == 1
responses['http://www.pauldix.net/'].should == 404
end
end
end
describe "#fetch_and_parse" do
it "passes options to multicurl" do
options = { user_agent: '007' }
Feedzirra::Feed.should_receive(:add_url_to_multi).
with(anything, anything, anything, anything, options)
Feedzirra::Feed.fetch_and_parse(sample_rss_feed, options)
end
end
describe "#decode_content" do
before(:each) do
@curl_easy = double('curl_easy', :body_str => '')
end
it 'should decode the response body using gzip if the Content-Encoding: is gzip' do
@curl_easy.stub(:header_str).and_return('Content-Encoding: gzip')
string_io = double('stringio', :read => @curl_easy.body_str, :close => true)
StringIO.should_receive(:new).and_return(string_io)
Zlib::GzipReader.should_receive(:new).with(string_io).and_return(string_io)
Feedzirra::Feed.decode_content(@curl_easy)
end
it 'should decode the response body using gzip if the Content-Encoding: is gzip even when the case is wrong' do
@curl_easy.stub(:header_str).and_return('content-encoding: gzip')
string_io = double('stringio', :read => @curl_easy.body_str, :close => true)
StringIO.should_receive(:new).and_return(string_io)
Zlib::GzipReader.should_receive(:new).with(string_io).and_return(string_io)
Feedzirra::Feed.decode_content(@curl_easy)
end
it 'should deflate the response body using inflate if the Content-Encoding: is deflate' do
@curl_easy.stub(:header_str).and_return('Content-Encoding: deflate')
Zlib::Inflate.should_receive(:inflate).with(@curl_easy.body_str)
Feedzirra::Feed.decode_content(@curl_easy)
end
it 'should deflate the response body using inflate if the Content-Encoding: is deflate event if the case is wrong' do
@curl_easy.stub(:header_str).and_return('content-encoding: deflate')
Zlib::Inflate.should_receive(:inflate).with(@curl_easy.body_str)
Feedzirra::Feed.decode_content(@curl_easy)
end
it 'should return the response body if it is not encoded' do
@curl_easy.stub(:header_str).and_return('')
Feedzirra::Feed.decode_content(@curl_easy).should == ''
end
end
describe "#update" do
it "passes options to multicurl" do
options = { user_agent: '007' }
Feedzirra::Feed.should_receive(:add_feed_to_multi).
with(anything, anything, anything, anything, options)
Feedzirra::Feed.update(sample_rss_feed, options)
end
end
end
end