fblee-feedzirra 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -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