fblee-feedzirra 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,595 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Feedzirra::Feed do
4
+ describe "#add_common_feed_entry_element" do
5
+ before(:all) do
6
+ Feedzirra::Feed.add_common_feed_entry_element("wfw:commentRss", :as => :comment_rss)
7
+ end
8
+
9
+ it "should parse the added element out of Atom feeds" do
10
+ Feedzirra::Feed.parse(sample_wfw_feed).entries.first.comment_rss.should == "this is the new val"
11
+ end
12
+
13
+ it "should parse the added element out of Atom Feedburner feeds" do
14
+ Feedzirra::Parser::AtomEntry.new.should respond_to(:comment_rss)
15
+ end
16
+
17
+ it "should parse the added element out of RSS feeds" do
18
+ Feedzirra::Parser::RSSEntry.new.should respond_to(:comment_rss)
19
+ end
20
+ end
21
+
22
+ describe "#parse" do # many of these tests are redundant with the specific feed type tests, but I put them here for completeness
23
+ context "when there's an available parser" do
24
+ it "should parse an rdf feed" do
25
+ feed = Feedzirra::Feed.parse(sample_rdf_feed)
26
+ feed.title.should == "HREF Considered Harmful"
27
+ feed.entries.first.published.to_s.should == "Tue Sep 02 19:50:07 UTC 2008"
28
+ feed.entries.size.should == 10
29
+ end
30
+
31
+ it "should parse an rss feed" do
32
+ feed = Feedzirra::Feed.parse(sample_rss_feed)
33
+ feed.title.should == "Tender Lovemaking"
34
+ feed.entries.first.published.to_s.should == "Thu Dec 04 17:17:49 UTC 2008"
35
+ feed.entries.size.should == 10
36
+ end
37
+
38
+ it "should parse an atom feed" do
39
+ feed = Feedzirra::Feed.parse(sample_atom_feed)
40
+ feed.title.should == "Amazon Web Services Blog"
41
+ feed.entries.first.published.to_s.should == "Fri Jan 16 18:21:00 UTC 2009"
42
+ feed.entries.size.should == 10
43
+ end
44
+
45
+ it "should parse an feedburner atom feed" do
46
+ feed = Feedzirra::Feed.parse(sample_feedburner_atom_feed)
47
+ feed.title.should == "Paul Dix Explains Nothing"
48
+ feed.entries.first.published.to_s.should == "Thu Jan 22 15:50:22 UTC 2009"
49
+ feed.entries.size.should == 5
50
+ end
51
+
52
+ it "should parse a web page" do
53
+ real_bbc_rss_url = "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml"
54
+ feed = Feedzirra::WebPage.parse(sample_web_page)
55
+ feed.feed_url.should == real_bbc_rss_url
56
+
57
+ real_avc_url = 'http://feeds.feedburner.com/AVc'
58
+ feed = Feedzirra::WebPage.parse(sample_web_page2)
59
+ feed.feed_url.should == real_avc_url
60
+
61
+ end
62
+
63
+ it "should parse BBC news and get the RSS feed" do
64
+ bbc_web_url = 'http://news.bbc.co.uk/'
65
+ real_bbc_rss_url = "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml"
66
+ feed = Feedzirra::Feed.fetch_and_parse(bbc_web_url)
67
+ feed.title.should == 'BBC News | News Front Page | UK Edition'
68
+ feed.feed_url.should == real_bbc_rss_url
69
+ feed.entries.size.should > 0
70
+
71
+ real_avc_url = 'http://feeds.feedburner.com/AVc'
72
+ # for this test, avc.com is where you visit, but the feed itself reports its
73
+ # canonical location as www.avc.com/a_vc/ which is fine, but means this test looks
74
+ # a bit weird!
75
+ avc_web_url = 'http://www.avc.com/'
76
+ avc_home_url = 'http://www.avc.com/a_vc/'
77
+ feed = Feedzirra::Feed.fetch_and_parse(avc_web_url)
78
+ feed.feed_url.should == real_avc_url
79
+ feed.url.should == avc_home_url
80
+ feed.entries.size.should > 0
81
+ end
82
+
83
+ it "should extract image URLs" do
84
+ feed = Feedzirra::Feed.parse(sample_rss_with_images)
85
+ feed.entries.size.should > 0
86
+ feed.entries[0].image.should == 'http://www.gravatar.com/avatar/5c6727e573b7be20dea6a6880856a888?s=96&d=identicon'
87
+ end
88
+
89
+ it "should determine parser correctly" do
90
+ feed = Feedzirra::Feed.parse(sample_problematic_parser_detection)
91
+ feed.entries.size.should > 0
92
+ feed = Feedzirra::Feed.fetch_and_parse('http://www.independent.co.uk/news/world/rss')
93
+ feed.entries.size.should > 0
94
+ #puts feed.title
95
+ end
96
+
97
+ it "should parse an itunes feed as a standard RSS feed" do
98
+ feed = Feedzirra::Feed.parse(sample_itunes_feed)
99
+ feed.title.should == "All About Everything"
100
+ feed.entries.first.published.should == Time.parse("Wed, 15 Jun 2005 19:00:00 GMT")
101
+
102
+ # Since the commit 621957879, iTunes feeds will be parsed as standard RSS, so this
103
+ # entry should now not have a method for itunes_author.
104
+ feed.entries.first.should_not respond_to(:itunes_author)
105
+ feed.entries.size.should == 3
106
+ end
107
+ end
108
+
109
+ context "when there's no available parser" do
110
+ it "raises Feedzirra::NoParserAvailable" do
111
+ proc {
112
+ Feedzirra::Feed.parse("I'm an invalid feed")
113
+ }.should raise_error(Feedzirra::NoParserAvailable)
114
+ end
115
+ end
116
+
117
+ it "should parse an feedburner rss feed" do
118
+ feed = Feedzirra::Feed.parse(sample_rss_feed_burner_feed)
119
+ feed.title.should == "Sam Harris: Author, Philosopher, Essayist, Atheist"
120
+ feed.entries.first.published.to_s.should == "Tue Jan 13 17:20:28 UTC 2009"
121
+ feed.entries.size.should == 10
122
+ end
123
+ end
124
+
125
+ describe "#determine_feed_parser_for_xml" do
126
+ it "should return the Feedzirra::Parser::Atom class for an atom feed" do
127
+ Feedzirra::Feed.determine_feed_parser_for_xml(sample_atom_feed).should == Feedzirra::Parser::Atom
128
+ end
129
+
130
+ it "should return the Feedzirra::Parser::AtomFeedBurner class for an atom feedburner feed" do
131
+ Feedzirra::Feed.determine_feed_parser_for_xml(sample_feedburner_atom_feed).should == Feedzirra::Parser::AtomFeedBurner
132
+ end
133
+
134
+ it "should return the Feedzirra::Parser::RSS class for an rdf/rss 1.0 feed" do
135
+ Feedzirra::Feed.determine_feed_parser_for_xml(sample_rdf_feed).should == Feedzirra::Parser::RSS
136
+ end
137
+
138
+ it "should return the Feedzirra::Parser::RSS class for an rss feedburner feed" do
139
+ Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed_burner_feed).should == Feedzirra::Parser::RSS
140
+ end
141
+
142
+ it "should return the Feedzirra::Parser::RSS object for an rss 2.0 feed" do
143
+ Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed).should == Feedzirra::Parser::RSS
144
+ end
145
+
146
+ it "should return a Feedzirra::Parser::RSS object for an itunes feed" do
147
+ Feedzirra::Feed.determine_feed_parser_for_xml(sample_itunes_feed).should == Feedzirra::Parser::RSS
148
+ end
149
+
150
+ end
151
+
152
+ describe "when adding feed types" do
153
+ it "should prioritize added types over the built in ones" do
154
+ feed_text = "Atom asdf"
155
+ Feedzirra::Parser::Atom.should be_able_to_parse(feed_text)
156
+ new_feed_type = Class.new do
157
+ def self.able_to_parse?(val)
158
+ true
159
+ end
160
+ end
161
+
162
+ new_feed_type.should be_able_to_parse(feed_text)
163
+ Feedzirra::Feed.add_feed_class(new_feed_type)
164
+ Feedzirra::Feed.determine_feed_parser_for_xml(feed_text).should == new_feed_type
165
+
166
+ # this is a hack so that this doesn't break the rest of the tests
167
+ Feedzirra::Feed.feed_classes.reject! {|o| o == new_feed_type }
168
+ end
169
+ end
170
+
171
+ describe '#etag_from_header' do
172
+ before(:each) do
173
+ @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"
174
+ end
175
+
176
+ it "should return the etag from the header if it exists" do
177
+ Feedzirra::Feed.etag_from_header(@header).should == "ziEyTl4q9GH04BR4jgkImd0GvSE"
178
+ end
179
+
180
+ it "should return nil if there is no etag in the header" do
181
+ Feedzirra::Feed.etag_from_header("foo").should be_nil
182
+ end
183
+
184
+ end
185
+
186
+ describe '#last_modified_from_header' do
187
+ before(:each) do
188
+ @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"
189
+ end
190
+
191
+ it "should return the last modified date from the header if it exists" do
192
+ Feedzirra::Feed.last_modified_from_header(@header).should == Time.parse("Wed, 28 Jan 2009 04:10:32 GMT")
193
+ end
194
+
195
+ it "should return nil if there is no last modified date in the header" do
196
+ Feedzirra::Feed.last_modified_from_header("foo").should be_nil
197
+ end
198
+ end
199
+
200
+ describe "fetching feeds" do
201
+ before(:each) do
202
+ @paul_feed = { :xml => load_sample("PaulDixExplainsNothing.xml"), :url => "http://feeds.feedburner.com/PaulDixExplainsNothing" }
203
+ @trotter_feed = { :xml => load_sample("TrotterCashionHome.xml"), :url => "http://feeds2.feedburner.com/trottercashion" }
204
+ end
205
+
206
+ describe "#fetch_raw" do
207
+ before(:each) do
208
+ @cmock = stub('cmock', :header_str => '', :body_str => @paul_feed[:xml] )
209
+ @multi = stub('curl_multi', :add => true, :perform => true)
210
+ @curl_easy = stub('curl_easy')
211
+ @curl = stub('curl', :headers => {}, :follow_location= => true, :on_failure => true)
212
+ @curl.stub!(:on_success).and_yield(@cmock)
213
+
214
+ Curl::Multi.stub!(:new).and_return(@multi)
215
+ Curl::Easy.stub!(:new).and_yield(@curl).and_return(@curl_easy)
216
+ end
217
+
218
+ it "should set user agent if it's passed as an option" do
219
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url], :user_agent => 'Custom Useragent')
220
+ @curl.headers['User-Agent'].should == 'Custom Useragent'
221
+ end
222
+
223
+ it "should set user agent to default if it's not passed as an option" do
224
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url])
225
+ @curl.headers['User-Agent'].should == Feedzirra::Feed::USER_AGENT
226
+ end
227
+
228
+ it "should return raw xml" do
229
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url]).should =~ /^#{Regexp.escape('<?xml version="1.0" encoding="utf-8"?>')}/i
230
+ end
231
+
232
+ it "should set if modified since as an option if passed" do
233
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url], :if_modified_since => Time.parse("Wed, 28 Jan 2009 04:10:32 GMT"))
234
+ @curl.headers["If-Modified-Since"].should == 'Wed, 28 Jan 2009 04:10:32 GMT'
235
+ end
236
+
237
+ it "should set if none match as an option if passed" do
238
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url], :if_none_match => 'ziEyTl4q9GH04BR4jgkImd0GvSE')
239
+ @curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
240
+ end
241
+
242
+ it 'should set userpwd for http basic authentication if :http_authentication is passed' do
243
+ @curl.should_receive(:userpwd=).with('username:password')
244
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url], :http_authentication => ['username', 'password'])
245
+ end
246
+
247
+ it 'should set accepted encodings' do
248
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url], :compress => true)
249
+ @curl.headers["Accept-encoding"].should == 'gzip, deflate'
250
+ end
251
+
252
+ it "should return raw xml" do
253
+ Feedzirra::Feed.fetch_raw(@paul_feed[:url]).should =~ /^#{Regexp.escape('<?xml version="1.0" encoding="UTF-8"?>')}/
254
+ end
255
+
256
+ it "should take multiple feed urls and return a hash of urls and response xml" do
257
+ multi = stub('curl_multi', :add => true, :perform => true)
258
+ Curl::Multi.stub!(:new).and_return(multi)
259
+
260
+ paul_response = stub('paul_response', :header_str => '', :body_str => @paul_feed[:xml] )
261
+ trotter_response = stub('trotter_response', :header_str => '', :body_str => @trotter_feed[:xml] )
262
+
263
+ paul_curl = stub('paul_curl', :headers => {}, :follow_location= => true, :on_failure => true)
264
+ paul_curl.stub!(:on_success).and_yield(paul_response)
265
+
266
+ trotter_curl = stub('trotter_curl', :headers => {}, :follow_location= => true, :on_failure => true)
267
+ trotter_curl.stub!(:on_success).and_yield(trotter_response)
268
+
269
+ Curl::Easy.should_receive(:new).with(@paul_feed[:url]).ordered.and_yield(paul_curl)
270
+ Curl::Easy.should_receive(:new).with(@trotter_feed[:url]).ordered.and_yield(trotter_curl)
271
+
272
+ results = Feedzirra::Feed.fetch_raw([@paul_feed[:url], @trotter_feed[:url]])
273
+ results.keys.should include(@paul_feed[:url])
274
+ results.keys.should include(@trotter_feed[:url])
275
+ results[@paul_feed[:url]].should =~ /Paul Dix/
276
+ results[@trotter_feed[:url]].should =~ /Trotter Cashion/
277
+ end
278
+
279
+ it "should always return a hash when passed an array" do
280
+ results = Feedzirra::Feed.fetch_raw([@paul_feed[:url]])
281
+ results.class.should == Hash
282
+ end
283
+ end
284
+
285
+ describe "#add_url_to_multi" do
286
+ before(:each) do
287
+ @multi = Curl::Multi.new(@paul_feed[:url])
288
+ @multi.stub!(:add)
289
+ @easy_curl = Curl::Easy.new(@paul_feed[:url])
290
+
291
+ Curl::Easy.should_receive(:new).and_yield(@easy_curl)
292
+ end
293
+
294
+ it "should set user agent if it's passed as an option" do
295
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :user_agent => 'My cool application')
296
+ @easy_curl.headers["User-Agent"].should == 'My cool application'
297
+ end
298
+
299
+ it "should set user agent to default if it's not passed as an option" do
300
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
301
+ @easy_curl.headers["User-Agent"].should == Feedzirra::Feed::USER_AGENT
302
+ end
303
+
304
+ it "should set if modified since as an option if passed" do
305
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :if_modified_since => Time.parse("Jan 25 2009 04:10:32 GMT"))
306
+ @easy_curl.headers["If-Modified-Since"].should == 'Sun, 25 Jan 2009 04:10:32 GMT'
307
+ end
308
+
309
+ it 'should set follow location to true' do
310
+ @easy_curl.should_receive(:follow_location=).with(true)
311
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
312
+ end
313
+
314
+ it 'should set userpwd for http basic authentication if :http_authentication is passed' do
315
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :http_authentication => ['myusername', 'mypassword'])
316
+ @easy_curl.userpwd.should == 'myusername:mypassword'
317
+ end
318
+
319
+ it 'should set accepted encodings' do
320
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {:compress => true})
321
+ @easy_curl.headers["Accept-encoding"].should == 'gzip, deflate'
322
+ end
323
+
324
+ it "should set if_none_match as an option if passed" do
325
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :if_none_match => 'ziEyTl4q9GH04BR4jgkImd0GvSE')
326
+ @easy_curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
327
+ end
328
+
329
+ describe 'on success' do
330
+ before(:each) do
331
+ @feed = mock('feed', :feed_url= => true, :etag= => true, :last_modified= => true)
332
+ Feedzirra::Feed.stub!(:decode_content).and_return(@paul_feed[:xml])
333
+ Feedzirra::Feed.stub!(:determine_feed_parser_for_xml).and_return(Feedzirra::Parser::AtomFeedBurner)
334
+ Feedzirra::Parser::AtomFeedBurner.stub!(:parse).and_return(@feed)
335
+ Feedzirra::Feed.stub!(:etag_from_header).and_return('ziEyTl4q9GH04BR4jgkImd0GvSE')
336
+ Feedzirra::Feed.stub!(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
337
+ end
338
+
339
+ it 'should decode the response body' do
340
+ Feedzirra::Feed.should_receive(:decode_content).with(@easy_curl).and_return(@paul_feed[:xml])
341
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
342
+ @easy_curl.on_success.call(@easy_curl)
343
+ end
344
+
345
+ it 'should determine the xml parser class' do
346
+ Feedzirra::Feed.should_receive(:determine_feed_parser_for_xml).with(@paul_feed[:xml]).and_return(Feedzirra::Parser::AtomFeedBurner)
347
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
348
+ @easy_curl.on_success.call(@easy_curl)
349
+ end
350
+
351
+ it 'should parse the xml' do
352
+ Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).with(@paul_feed[:xml]).and_return(@feed)
353
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
354
+ @easy_curl.on_success.call(@easy_curl)
355
+ end
356
+
357
+ describe 'when a compatible xml parser class is found' do
358
+ it 'should set the last effective url to the feed url' do
359
+ @easy_curl.should_receive(:last_effective_url).and_return(@paul_feed[:url])
360
+ @feed.should_receive(:feed_url=).with(@paul_feed[:url])
361
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
362
+ @easy_curl.on_success.call(@easy_curl)
363
+ end
364
+
365
+ it 'should set the etags on the feed' do
366
+ @feed.should_receive(:etag=).with('ziEyTl4q9GH04BR4jgkImd0GvSE')
367
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
368
+ @easy_curl.on_success.call(@easy_curl)
369
+ end
370
+
371
+ it 'should set the last modified on the feed' do
372
+ @feed.should_receive(:last_modified=).with('Wed, 28 Jan 2009 04:10:32 GMT')
373
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
374
+ @easy_curl.on_success.call(@easy_curl)
375
+ end
376
+
377
+ it 'should add the feed to the responses' do
378
+ responses = {}
379
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
380
+ @easy_curl.on_success.call(@easy_curl)
381
+
382
+ responses.length.should == 1
383
+ responses['http://feeds.feedburner.com/PaulDixExplainsNothing'].should == @feed
384
+ end
385
+
386
+ it 'should call proc if :on_success option is passed' do
387
+ success = lambda { |url, feed| }
388
+ success.should_receive(:call).with(@paul_feed[:url], @feed)
389
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_success => success })
390
+ @easy_curl.on_success.call(@easy_curl)
391
+ end
392
+ end
393
+
394
+ describe 'when no compatible xml parser class is found' do
395
+ it 'should raise a NoParserAvailable exception'
396
+ end
397
+ end
398
+
399
+ describe 'on failure' do
400
+ before(:each) do
401
+ @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"
402
+ @body = 'Page could not be found.'
403
+
404
+ @easy_curl.stub!(:response_code).and_return(404)
405
+ @easy_curl.stub!(:header_str).and_return(@headers)
406
+ @easy_curl.stub!(:body_str).and_return(@body)
407
+ end
408
+
409
+ it 'should call proc if :on_failure option is passed' do
410
+ failure = lambda { |url, feed| }
411
+ failure.should_receive(:call).with(@paul_feed[:url], 404, @headers, @body)
412
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_failure => failure })
413
+ @easy_curl.on_failure.call(@easy_curl)
414
+ end
415
+
416
+ it 'should return the http code in the responses' do
417
+ responses = {}
418
+ Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
419
+ @easy_curl.on_failure.call(@easy_curl)
420
+
421
+ responses.length.should == 1
422
+ responses[@paul_feed[:url]].should == 404
423
+ end
424
+ end
425
+ end
426
+
427
+ describe "#add_feed_to_multi" do
428
+ before(:each) do
429
+ @multi = Curl::Multi.new(@paul_feed[:url])
430
+ @multi.stub!(:add)
431
+ @easy_curl = Curl::Easy.new(@paul_feed[:url])
432
+ @feed = Feedzirra::Feed.parse(sample_feedburner_atom_feed)
433
+
434
+ Curl::Easy.should_receive(:new).and_yield(@easy_curl)
435
+ end
436
+
437
+ it "should set user agent if it's passed as an option" do
438
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, :user_agent => 'My cool application')
439
+ @easy_curl.headers["User-Agent"].should == 'My cool application'
440
+ end
441
+
442
+ it "should set user agent to default if it's not passed as an option" do
443
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
444
+ @easy_curl.headers["User-Agent"].should == Feedzirra::Feed::USER_AGENT
445
+ end
446
+
447
+ it "should set if modified since as an option if passed"
448
+
449
+ it 'should set follow location to true' do
450
+ @easy_curl.should_receive(:follow_location=).with(true)
451
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
452
+ end
453
+
454
+ it 'should set userpwd for http basic authentication if :http_authentication is passed' do
455
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, :http_authentication => ['myusername', 'mypassword'])
456
+ @easy_curl.userpwd.should == 'myusername:mypassword'
457
+ end
458
+
459
+ it "should set if_none_match as an option if passed" do
460
+ @feed.etag = 'ziEyTl4q9GH04BR4jgkImd0GvSE'
461
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
462
+ @easy_curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
463
+ end
464
+
465
+ describe 'on success' do
466
+ before(:each) do
467
+ @new_feed = @feed.clone
468
+ @feed.stub!(:update_from_feed)
469
+ Feedzirra::Feed.stub!(:decode_content).and_return(@paul_feed[:xml])
470
+ Feedzirra::Feed.stub!(:determine_feed_parser_for_xml).and_return(Feedzirra::Parser::AtomFeedBurner)
471
+ Feedzirra::Parser::AtomFeedBurner.stub!(:parse).and_return(@new_feed)
472
+ Feedzirra::Feed.stub!(:etag_from_header).and_return('ziEyTl4q9GH04BR4jgkImd0GvSE')
473
+ Feedzirra::Feed.stub!(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
474
+ end
475
+
476
+ it 'should process the next feed in the queue'
477
+
478
+ it 'should parse the updated feed' do
479
+ Feedzirra::Parser::AtomFeedBurner.should_receive(:parse).and_return(@new_feed)
480
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
481
+ @easy_curl.on_success.call(@easy_curl)
482
+ end
483
+
484
+ it 'should set the last effective url to the feed url' do
485
+ @easy_curl.should_receive(:last_effective_url).and_return(@paul_feed[:url])
486
+ @new_feed.should_receive(:feed_url=).with(@paul_feed[:url])
487
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
488
+ @easy_curl.on_success.call(@easy_curl)
489
+ end
490
+
491
+ it 'should set the etags on the feed' do
492
+ @new_feed.should_receive(:etag=).with('ziEyTl4q9GH04BR4jgkImd0GvSE')
493
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
494
+ @easy_curl.on_success.call(@easy_curl)
495
+ end
496
+
497
+ it 'should set the last modified on the feed' do
498
+ @new_feed.should_receive(:last_modified=).with('Wed, 28 Jan 2009 04:10:32 GMT')
499
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
500
+ @easy_curl.on_success.call(@easy_curl)
501
+ end
502
+
503
+ it 'should add the feed to the responses' do
504
+ responses = {}
505
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], responses, {})
506
+ @easy_curl.on_success.call(@easy_curl)
507
+
508
+ responses.length.should == 1
509
+ responses['http://feeds.feedburner.com/PaulDixExplainsNothing'].should == @feed
510
+ end
511
+
512
+ it 'should call proc if :on_success option is passed' do
513
+ success = lambda { |feed| }
514
+ success.should_receive(:call).with(@feed)
515
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
516
+ @easy_curl.on_success.call(@easy_curl)
517
+ end
518
+
519
+ it 'should call update from feed on the old feed with the updated feed' do
520
+ @feed.should_receive(:update_from_feed).with(@new_feed)
521
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
522
+ @easy_curl.on_success.call(@easy_curl)
523
+ end
524
+ end
525
+
526
+ describe 'on failure' do
527
+ before(:each) do
528
+ @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"
529
+ @body = 'Page could not be found.'
530
+
531
+ @easy_curl.stub!(:response_code).and_return(404)
532
+ @easy_curl.stub!(:header_str).and_return(@headers)
533
+ @easy_curl.stub!(:body_str).and_return(@body)
534
+ end
535
+
536
+ it 'should call on success callback if the response code is 304' do
537
+ success = lambda { |feed| }
538
+ success.should_receive(:call).with(@feed)
539
+ @easy_curl.should_receive(:response_code).and_return(304)
540
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
541
+ @easy_curl.on_failure.call(@easy_curl)
542
+ end
543
+
544
+ it 'should return the http code in the responses' do
545
+ responses = {}
546
+ Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], responses, {})
547
+ @easy_curl.on_failure.call(@easy_curl)
548
+
549
+ responses.length.should == 1
550
+ responses['http://www.pauldix.net/'].should == 404
551
+ end
552
+ end
553
+ end
554
+
555
+ describe "#fetch_and_parse" do
556
+ it 'should initiate the fetching and parsing using multicurl'
557
+ it "should pass any request options through to add_url_to_multi"
558
+ it 'should slice the feeds into groups of thirty for processing'
559
+ it "should return a feed object if a single feed is passed in"
560
+ it "should return an return an array of feed objects if multiple feeds are passed in"
561
+ end
562
+
563
+ describe "#decode_content" do
564
+ before(:each) do
565
+ @curl_easy = mock('curl_easy', :body_str => '<xml></xml>')
566
+ end
567
+
568
+ it 'should decode the response body using gzip if the Content-Encoding: is gzip' do
569
+ @curl_easy.stub!(:header_str).and_return('Content-Encoding: gzip')
570
+ string_io = mock('stringio', :read => @curl_easy.body_str, :close => true)
571
+ StringIO.should_receive(:new).and_return(string_io)
572
+ Zlib::GzipReader.should_receive(:new).with(string_io).and_return(string_io)
573
+ Feedzirra::Feed.decode_content(@curl_easy)
574
+ end
575
+
576
+ it 'should deflate the response body using inflate if the Content-Encoding: is deflate' do
577
+ @curl_easy.stub!(:header_str).and_return('Content-Encoding: deflate')
578
+ Zlib::Inflate.should_receive(:inflate).with(@curl_easy.body_str)
579
+ Feedzirra::Feed.decode_content(@curl_easy)
580
+ end
581
+
582
+ it 'should return the response body if it is not encoded' do
583
+ @curl_easy.stub!(:header_str).and_return('')
584
+ Feedzirra::Feed.decode_content(@curl_easy).should == '<xml></xml>'
585
+ end
586
+ end
587
+
588
+ describe "#update" do
589
+ it 'should perform the updating using multicurl'
590
+ it "should pass any request options through to add_feed_to_multi"
591
+ it "should return a feed object if a single feed is passed in"
592
+ it "should return an return an array of feed objects if multiple feeds are passed in"
593
+ end
594
+ end
595
+ end