pauldix-feedzirra 0.0.3 → 0.0.5
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.
- data/README.textile +1 -1
- data/Rakefile +39 -0
- data/lib/core_ext/string.rb +9 -0
- data/lib/feedzirra/atom.rb +9 -1
- data/lib/feedzirra/atom_entry.rb +11 -0
- data/lib/feedzirra/atom_feed_burner.rb +9 -1
- data/lib/feedzirra/atom_feed_burner_entry.rb +11 -0
- data/lib/feedzirra/feed.rb +168 -27
- data/lib/feedzirra/feed_entry_utilities.rb +1 -23
- data/lib/feedzirra/itunes_rss.rb +46 -0
- data/lib/feedzirra/itunes_rss_item.rb +28 -0
- data/lib/feedzirra/itunes_rss_owner.rb +8 -0
- data/lib/feedzirra/rdf.rb +9 -1
- data/lib/feedzirra/rdf_entry.rb +10 -0
- data/lib/feedzirra/rss.rb +9 -1
- data/lib/feedzirra/rss_entry.rb +11 -0
- data/lib/feedzirra.rb +5 -0
- data/spec/feedzirra/feed_spec.rb +415 -123
- data/spec/feedzirra/itunes_rss_item_spec.rb +48 -0
- data/spec/feedzirra/itunes_rss_owner_spec.rb +18 -0
- data/spec/feedzirra/itunes_rss_spec.rb +50 -0
- data/spec/spec_helper.rb +21 -9
- metadata +8 -1
data/spec/feedzirra/feed_spec.rb
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
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::AtomEntry.new.should respond_to(:comment_rss)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should parse the added element out of RSS feeds" do
|
18
|
+
Feedzirra::RSSEntry.new.should respond_to(:comment_rss)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
4
22
|
describe "#parse" do # many of these tests are redundant with the specific feed type tests, but I put them here for completeness
|
5
23
|
context "when there's an available parser" do
|
6
24
|
it "should parse an rdf feed" do
|
@@ -30,16 +48,24 @@ describe Feedzirra::Feed do
|
|
30
48
|
feed.entries.first.published.to_s.should == "Thu Jan 22 15:50:22 UTC 2009"
|
31
49
|
feed.entries.size.should == 5
|
32
50
|
end
|
51
|
+
|
52
|
+
it "should parse an itunes feed" do
|
53
|
+
feed = Feedzirra::Feed.parse(sample_itunes_feed)
|
54
|
+
feed.title.should == "All About Everything"
|
55
|
+
feed.entries.first.published.to_s.should == "Wed, 15 Jun 2005 19:00:00 GMT"
|
56
|
+
feed.entries.first.itunes_author.should == "John Doe"
|
57
|
+
feed.entries.size.should == 3
|
58
|
+
end
|
33
59
|
end
|
34
|
-
|
60
|
+
|
35
61
|
context "when there's no available parser" do
|
36
62
|
it "raises Feedzirra::NoParserAvailable" do
|
37
63
|
proc {
|
38
64
|
Feedzirra::Feed.parse("I'm an invalid feed")
|
39
65
|
}.should raise_error(Feedzirra::NoParserAvailable)
|
40
|
-
end
|
66
|
+
end
|
41
67
|
end
|
42
|
-
|
68
|
+
|
43
69
|
it "should parse an feedburner rss feed" do
|
44
70
|
feed = Feedzirra::Feed.parse(sample_rss_feed_burner_feed)
|
45
71
|
feed.title.should == "Sam Harris: Author, Philosopher, Essayist, Atheist"
|
@@ -47,31 +73,36 @@ describe Feedzirra::Feed do
|
|
47
73
|
feed.entries.size.should == 10
|
48
74
|
end
|
49
75
|
end
|
50
|
-
|
76
|
+
|
51
77
|
describe "#determine_feed_parser_for_xml" do
|
52
78
|
it "should return the Feedzirra::Atom class for an atom feed" do
|
53
79
|
Feedzirra::Feed.determine_feed_parser_for_xml(sample_atom_feed).should == Feedzirra::Atom
|
54
80
|
end
|
55
|
-
|
81
|
+
|
56
82
|
it "should return the Feedzirra::AtomFeedBurner class for an atom feedburner feed" do
|
57
83
|
Feedzirra::Feed.determine_feed_parser_for_xml(sample_feedburner_atom_feed).should == Feedzirra::AtomFeedBurner
|
58
84
|
end
|
59
|
-
|
85
|
+
|
60
86
|
it "should return the Feedzirra::RSS class for an rdf/rss 1.0 feed" do
|
61
87
|
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rdf_feed).should == Feedzirra::RSS
|
62
88
|
end
|
63
|
-
|
89
|
+
|
64
90
|
it "should return the Feedzirra::RSS class for an rss feedburner feed" do
|
65
91
|
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed_burner_feed).should == Feedzirra::RSS
|
66
92
|
end
|
67
|
-
|
93
|
+
|
68
94
|
it "should return the Feedzirra::RSS object for an rss 2.0 feed" do
|
69
95
|
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed).should == Feedzirra::RSS
|
70
96
|
end
|
97
|
+
|
98
|
+
it "should return the Feedzirra::ITunesRSS object for an itunes feed" do
|
99
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(sample_itunes_feed).should == Feedzirra::ITunesRSS
|
100
|
+
end
|
101
|
+
|
71
102
|
end
|
72
|
-
|
73
|
-
describe "adding feed types" do
|
74
|
-
it "should prioritize added
|
103
|
+
|
104
|
+
describe "when adding feed types" do
|
105
|
+
it "should prioritize added types over the built in ones" do
|
75
106
|
feed_text = "Atom asdf"
|
76
107
|
Feedzirra::Atom.should be_able_to_parse(feed_text)
|
77
108
|
new_feed_type = Class.new do
|
@@ -79,173 +110,434 @@ describe Feedzirra::Feed do
|
|
79
110
|
true
|
80
111
|
end
|
81
112
|
end
|
113
|
+
|
82
114
|
new_feed_type.should be_able_to_parse(feed_text)
|
83
115
|
Feedzirra::Feed.add_feed_class(new_feed_type)
|
84
116
|
Feedzirra::Feed.determine_feed_parser_for_xml(feed_text).should == new_feed_type
|
85
|
-
|
117
|
+
|
86
118
|
# this is a hack so that this doesn't break the rest of the tests
|
87
119
|
Feedzirra::Feed.feed_classes.reject! {|o| o == new_feed_type }
|
88
120
|
end
|
89
121
|
end
|
90
|
-
|
91
|
-
describe
|
122
|
+
|
123
|
+
describe '#etag_from_header' do
|
92
124
|
before(:each) do
|
93
125
|
@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"
|
94
126
|
end
|
95
|
-
|
96
|
-
it "should
|
127
|
+
|
128
|
+
it "should return the etag from the header if it exists" do
|
97
129
|
Feedzirra::Feed.etag_from_header(@header).should == "ziEyTl4q9GH04BR4jgkImd0GvSE"
|
98
130
|
end
|
99
|
-
|
100
|
-
it "should return nil if there is no etag in header" do
|
131
|
+
|
132
|
+
it "should return nil if there is no etag in the header" do
|
101
133
|
Feedzirra::Feed.etag_from_header("foo").should be_nil
|
102
134
|
end
|
103
|
-
|
104
|
-
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#last_modified_from_header' do
|
139
|
+
before(:each) do
|
140
|
+
@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"
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should return the last modified date from the header if it exists" do
|
105
144
|
Feedzirra::Feed.last_modified_from_header(@header).should == Time.parse("Wed, 28 Jan 2009 04:10:32 GMT")
|
106
145
|
end
|
107
|
-
|
108
|
-
it "should return nil if there is no last
|
146
|
+
|
147
|
+
it "should return nil if there is no last modified date in the header" do
|
109
148
|
Feedzirra::Feed.last_modified_from_header("foo").should be_nil
|
110
149
|
end
|
111
150
|
end
|
112
|
-
|
151
|
+
|
113
152
|
describe "fetching feeds" do
|
114
153
|
before(:each) do
|
115
|
-
@
|
116
|
-
@
|
117
|
-
end
|
118
|
-
|
119
|
-
describe "handling many feeds" do
|
120
|
-
it "should break a large number into more manageable blocks of 40"
|
121
|
-
it "should add to the queue as feeds finish (instead of waiting for each block of 40 to finsih)"
|
154
|
+
@paul_feed = { :xml => load_sample("PaulDixExplainsNothing.xml"), :url => "http://feeds.feedburner.com/PaulDixExplainsNothing" }
|
155
|
+
@trotter_feed = { :xml => load_sample("TrotterCashionHome.xml"), :url => "http://feeds2.feedburner.com/trottercashion" }
|
122
156
|
end
|
123
157
|
|
124
158
|
describe "#fetch_raw" do
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
159
|
+
before(:each) do
|
160
|
+
@cmock = stub('cmock', :header_str => '', :body_str => @paul_feed[:xml] )
|
161
|
+
@multi = stub('curl_multi', :add => true, :perform => true)
|
162
|
+
@curl_easy = stub('curl_easy')
|
163
|
+
@curl = stub('curl', :headers => {}, :follow_location= => true, :on_failure => true)
|
164
|
+
@curl.stub!(:on_success).and_yield(@cmock)
|
165
|
+
|
166
|
+
Curl::Multi.stub!(:new).and_return(@multi)
|
167
|
+
Curl::Easy.stub!(:new).and_yield(@curl).and_return(@curl_easy)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should set user agent if it's passed as an option" do
|
171
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :user_agent => 'Custom Useragent')
|
172
|
+
@curl.headers['User-Agent'].should == 'Custom Useragent'
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should set user agent to default if it's not passed as an option" do
|
176
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url])
|
177
|
+
@curl.headers['User-Agent'].should == Feedzirra::Feed::USER_AGENT
|
178
|
+
end
|
130
179
|
|
131
|
-
it "should
|
132
|
-
Feedzirra::Feed.fetch_raw(@
|
180
|
+
it "should set if modified since as an option if passed" do
|
181
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :if_modified_since => Time.parse("Wed, 28 Jan 2009 04:10:32 GMT"))
|
182
|
+
@curl.headers["If-Modified-Since"].should == 'Wed, 28 Jan 2009 04:10:32 GMT'
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should set if none match as an option if passed" do
|
186
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :if_none_match => 'ziEyTl4q9GH04BR4jgkImd0GvSE')
|
187
|
+
@curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
|
133
188
|
end
|
134
189
|
|
190
|
+
it 'should set userpwd for http basic authentication if :http_authentication is passed' do
|
191
|
+
@curl.should_receive(:userpwd=).with('username:password')
|
192
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url], :http_authentication => ['username', 'password'])
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should set accepted encodings' do
|
196
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url])
|
197
|
+
@curl.headers["Accept-encoding"].should == 'gzip, deflate'
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should return raw xml" do
|
201
|
+
Feedzirra::Feed.fetch_raw(@paul_feed[:url]).should =~ /^#{Regexp.escape('<?xml version="1.0" encoding="UTF-8"?>')}/
|
202
|
+
end
|
203
|
+
|
135
204
|
it "should take multiple feed urls and return a hash of urls and response xml" do
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
205
|
+
multi = stub('curl_multi', :add => true, :perform => true)
|
206
|
+
Curl::Multi.stub!(:new).and_return(multi)
|
207
|
+
|
208
|
+
paul_response = stub('paul_response', :header_str => '', :body_str => @paul_feed[:xml] )
|
209
|
+
trotter_response = stub('trotter_response', :header_str => '', :body_str => @trotter_feed[:xml] )
|
210
|
+
|
211
|
+
paul_curl = stub('paul_curl', :headers => {}, :follow_location= => true, :on_failure => true)
|
212
|
+
paul_curl.stub!(:on_success).and_yield(paul_response)
|
213
|
+
|
214
|
+
trotter_curl = stub('trotter_curl', :headers => {}, :follow_location= => true, :on_failure => true)
|
215
|
+
trotter_curl.stub!(:on_success).and_yield(trotter_response)
|
216
|
+
|
217
|
+
Curl::Easy.should_receive(:new).with(@paul_feed[:url]).ordered.and_yield(paul_curl)
|
218
|
+
Curl::Easy.should_receive(:new).with(@trotter_feed[:url]).ordered.and_yield(trotter_curl)
|
219
|
+
|
220
|
+
results = Feedzirra::Feed.fetch_raw([@paul_feed[:url], @trotter_feed[:url]])
|
221
|
+
results.keys.should include(@paul_feed[:url])
|
222
|
+
results.keys.should include(@trotter_feed[:url])
|
223
|
+
results[@paul_feed[:url]].should =~ /Paul Dix/
|
224
|
+
results[@trotter_feed[:url]].should =~ /Trotter Cashion/
|
141
225
|
end
|
142
|
-
|
226
|
+
|
143
227
|
it "should always return a hash when passed an array" do
|
144
|
-
results = Feedzirra::Feed.fetch_raw([@
|
228
|
+
results = Feedzirra::Feed.fetch_raw([@paul_feed[:url]])
|
145
229
|
results.class.should == Hash
|
146
230
|
end
|
147
231
|
end
|
148
|
-
|
149
|
-
describe "#
|
150
|
-
|
151
|
-
|
152
|
-
|
232
|
+
|
233
|
+
describe "#add_url_to_multi" do
|
234
|
+
before(:each) do
|
235
|
+
@multi = Curl::Multi.new(@paul_feed[:url])
|
236
|
+
@multi.stub!(:add)
|
237
|
+
@easy_curl = Curl::Easy.new(@paul_feed[:url])
|
238
|
+
|
239
|
+
Curl::Easy.should_receive(:new).and_yield(@easy_curl)
|
153
240
|
end
|
154
|
-
|
155
|
-
it "should set
|
156
|
-
|
157
|
-
|
241
|
+
|
242
|
+
it "should set user agent if it's passed as an option" do
|
243
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :user_agent => 'My cool application')
|
244
|
+
@easy_curl.headers["User-Agent"].should == 'My cool application'
|
158
245
|
end
|
159
246
|
|
160
|
-
it "should set
|
161
|
-
|
162
|
-
|
247
|
+
it "should set user agent to default if it's not passed as an option" do
|
248
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
249
|
+
@easy_curl.headers["User-Agent"].should == Feedzirra::Feed::USER_AGENT
|
163
250
|
end
|
164
251
|
|
165
|
-
it "should set
|
166
|
-
|
167
|
-
|
252
|
+
it "should set if modified since as an option if passed" do
|
253
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :if_modified_since => Time.parse("Jan 25 2009 04:10:32 GMT"))
|
254
|
+
@easy_curl.headers["If-Modified-Since"].should == 'Sun, 25 Jan 2009 04:10:32 GMT'
|
168
255
|
end
|
169
|
-
|
170
|
-
it
|
171
|
-
|
172
|
-
|
173
|
-
feeds[@paul_feed_url].feed_url.should == @paul_feed_url
|
174
|
-
feeds[@trotter_feed_url].feed_url.should == @trotter_feed_url
|
256
|
+
|
257
|
+
it 'should set follow location to true' do
|
258
|
+
@easy_curl.should_receive(:follow_location=).with(true)
|
259
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
175
260
|
end
|
176
261
|
|
177
|
-
it
|
178
|
-
|
179
|
-
|
262
|
+
it 'should set userpwd for http basic authentication if :http_authentication is passed' do
|
263
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :http_authentication => ['myusername', 'mypassword'])
|
264
|
+
@easy_curl.userpwd.should == 'myusername:mypassword'
|
180
265
|
end
|
181
266
|
|
182
|
-
it
|
183
|
-
|
184
|
-
|
185
|
-
Feedzirra::Feed.fetch_and_parse(@paul_feed_url, :on_success => lambda { |feed_url, feed|
|
186
|
-
feed_url.should == @paul_feed_url
|
187
|
-
feed.class.should == Feedzirra::AtomFeedBurner
|
188
|
-
successful_call_mock.call})
|
267
|
+
it 'should set accepted encodings' do
|
268
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
269
|
+
@easy_curl.headers["Accept-encoding"].should == 'gzip, deflate'
|
189
270
|
end
|
190
|
-
|
191
|
-
it "should
|
192
|
-
|
193
|
-
|
194
|
-
fail_url = "http://localhost"
|
195
|
-
Feedzirra::Feed.fetch_and_parse(fail_url, :on_failure => lambda {|feed_url, response_code, response_header, response_body|
|
196
|
-
feed_url.should == fail_url
|
197
|
-
response_code.should == 0
|
198
|
-
response_header.should == ""
|
199
|
-
response_body.should == ""
|
200
|
-
failure_call_mock.call})
|
271
|
+
|
272
|
+
it "should set if_none_match as an option if passed" do
|
273
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, :if_none_match => 'ziEyTl4q9GH04BR4jgkImd0GvSE')
|
274
|
+
@easy_curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
|
201
275
|
end
|
202
276
|
|
203
|
-
|
204
|
-
|
277
|
+
describe 'on success' do
|
278
|
+
before(:each) do
|
279
|
+
@feed = mock('feed', :feed_url= => true, :etag= => true, :last_modified= => true)
|
280
|
+
Feedzirra::Feed.stub!(:decode_content).and_return(@paul_feed[:xml])
|
281
|
+
Feedzirra::Feed.stub!(:determine_feed_parser_for_xml).and_return(Feedzirra::AtomFeedBurner)
|
282
|
+
Feedzirra::AtomFeedBurner.stub!(:parse).and_return(@feed)
|
283
|
+
Feedzirra::Feed.stub!(:etag_from_header).and_return('ziEyTl4q9GH04BR4jgkImd0GvSE')
|
284
|
+
Feedzirra::Feed.stub!(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'should decode the response body' do
|
288
|
+
Feedzirra::Feed.should_receive(:decode_content).with(@easy_curl).and_return(@paul_feed[:xml])
|
289
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
290
|
+
@easy_curl.on_success.call(@easy_curl)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'should determine the xml parser class' do
|
294
|
+
Feedzirra::Feed.should_receive(:determine_feed_parser_for_xml).with(@paul_feed[:xml]).and_return(Feedzirra::AtomFeedBurner)
|
295
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
296
|
+
@easy_curl.on_success.call(@easy_curl)
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'should parse the xml' do
|
300
|
+
Feedzirra::AtomFeedBurner.should_receive(:parse).with(@paul_feed[:xml]).and_return(@feed)
|
301
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
302
|
+
@easy_curl.on_success.call(@easy_curl)
|
303
|
+
end
|
304
|
+
|
305
|
+
describe 'when a compatible xml parser class is found' do
|
306
|
+
it 'should set the last effective url to the feed url' do
|
307
|
+
@easy_curl.should_receive(:last_effective_url).and_return(@paul_feed[:url])
|
308
|
+
@feed.should_receive(:feed_url=).with(@paul_feed[:url])
|
309
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
310
|
+
@easy_curl.on_success.call(@easy_curl)
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'should set the etags on the feed' do
|
314
|
+
@feed.should_receive(:etag=).with('ziEyTl4q9GH04BR4jgkImd0GvSE')
|
315
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
316
|
+
@easy_curl.on_success.call(@easy_curl)
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'should set the last modified on the feed' do
|
320
|
+
@feed.should_receive(:last_modified=).with('Wed, 28 Jan 2009 04:10:32 GMT')
|
321
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, {})
|
322
|
+
@easy_curl.on_success.call(@easy_curl)
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'should add the feed to the responses' do
|
326
|
+
responses = {}
|
327
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
|
328
|
+
@easy_curl.on_success.call(@easy_curl)
|
329
|
+
|
330
|
+
responses.length.should == 1
|
331
|
+
responses['http://feeds.feedburner.com/PaulDixExplainsNothing'].should == @feed
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'should call proc if :on_success option is passed' do
|
335
|
+
success = lambda { |url, feed| }
|
336
|
+
success.should_receive(:call).with(@paul_feed[:url], @feed)
|
337
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_success => success })
|
338
|
+
@easy_curl.on_success.call(@easy_curl)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
describe 'when no compatible xml parser class is found' do
|
343
|
+
it 'should raise a NoParserAvailable exception'
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe 'on failure' do
|
348
|
+
before(:each) do
|
349
|
+
@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"
|
350
|
+
@body = 'Page could not be found.'
|
351
|
+
|
352
|
+
@easy_curl.stub!(:response_code).and_return(404)
|
353
|
+
@easy_curl.stub!(:header_str).and_return(@headers)
|
354
|
+
@easy_curl.stub!(:body_str).and_return(@body)
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'should call proc if :on_failure option is passed' do
|
358
|
+
failure = lambda { |url, feed| }
|
359
|
+
failure.should_receive(:call).with(@paul_feed[:url], 404, @headers, @body)
|
360
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], {}, { :on_failure => failure })
|
361
|
+
@easy_curl.on_failure.call(@easy_curl)
|
362
|
+
end
|
363
|
+
|
364
|
+
it 'should return the http code in the responses' do
|
365
|
+
responses = {}
|
366
|
+
Feedzirra::Feed.add_url_to_multi(@multi, @paul_feed[:url], [], responses, {})
|
367
|
+
@easy_curl.on_failure.call(@easy_curl)
|
368
|
+
|
369
|
+
responses.length.should == 1
|
370
|
+
responses[@paul_feed[:url]].should == 404
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
describe "#add_feed_to_multi" do
|
376
|
+
before(:each) do
|
377
|
+
@multi = Curl::Multi.new(@paul_feed[:url])
|
378
|
+
@multi.stub!(:add)
|
379
|
+
@easy_curl = Curl::Easy.new(@paul_feed[:url])
|
380
|
+
@feed = Feedzirra::Feed.parse(sample_feedburner_atom_feed)
|
381
|
+
|
382
|
+
Curl::Easy.should_receive(:new).and_yield(@easy_curl)
|
383
|
+
end
|
384
|
+
|
385
|
+
it "should set user agent if it's passed as an option" do
|
386
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, :user_agent => 'My cool application')
|
387
|
+
@easy_curl.headers["User-Agent"].should == 'My cool application'
|
205
388
|
end
|
206
389
|
|
207
|
-
it "should set
|
208
|
-
|
209
|
-
|
390
|
+
it "should set user agent to default if it's not passed as an option" do
|
391
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
392
|
+
@easy_curl.headers["User-Agent"].should == Feedzirra::Feed::USER_AGENT
|
393
|
+
end
|
394
|
+
|
395
|
+
it "should set if modified since as an option if passed"
|
210
396
|
|
211
|
-
it
|
212
|
-
|
213
|
-
|
214
|
-
|
397
|
+
it 'should set follow location to true' do
|
398
|
+
@easy_curl.should_receive(:follow_location=).with(true)
|
399
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
400
|
+
end
|
215
401
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
402
|
+
it 'should set userpwd for http basic authentication if :http_authentication is passed' do
|
403
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, :http_authentication => ['myusername', 'mypassword'])
|
404
|
+
@easy_curl.userpwd.should == 'myusername:mypassword'
|
405
|
+
end
|
406
|
+
|
407
|
+
it "should set if_none_match as an option if passed" do
|
408
|
+
@feed.etag = 'ziEyTl4q9GH04BR4jgkImd0GvSE'
|
409
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
410
|
+
@easy_curl.headers["If-None-Match"].should == 'ziEyTl4q9GH04BR4jgkImd0GvSE'
|
411
|
+
end
|
412
|
+
|
413
|
+
describe 'on success' do
|
414
|
+
before(:each) do
|
415
|
+
@new_feed = @feed.clone
|
416
|
+
@feed.stub!(:update_from_feed)
|
417
|
+
Feedzirra::Feed.stub!(:decode_content).and_return(@paul_feed[:xml])
|
418
|
+
Feedzirra::Feed.stub!(:determine_feed_parser_for_xml).and_return(Feedzirra::AtomFeedBurner)
|
419
|
+
Feedzirra::AtomFeedBurner.stub!(:parse).and_return(@new_feed)
|
420
|
+
Feedzirra::Feed.stub!(:etag_from_header).and_return('ziEyTl4q9GH04BR4jgkImd0GvSE')
|
421
|
+
Feedzirra::Feed.stub!(:last_modified_from_header).and_return('Wed, 28 Jan 2009 04:10:32 GMT')
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'should process the next feed in the queue'
|
231
425
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
426
|
+
it 'should parse the updated feed' do
|
427
|
+
Feedzirra::AtomFeedBurner.should_receive(:parse).and_return(@new_feed)
|
428
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
429
|
+
@easy_curl.on_success.call(@easy_curl)
|
430
|
+
end
|
431
|
+
|
432
|
+
it 'should set the last effective url to the feed url' do
|
433
|
+
@easy_curl.should_receive(:last_effective_url).and_return(@paul_feed[:url])
|
434
|
+
@new_feed.should_receive(:feed_url=).with(@paul_feed[:url])
|
435
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
436
|
+
@easy_curl.on_success.call(@easy_curl)
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'should set the etags on the feed' do
|
440
|
+
@new_feed.should_receive(:etag=).with('ziEyTl4q9GH04BR4jgkImd0GvSE')
|
441
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
442
|
+
@easy_curl.on_success.call(@easy_curl)
|
443
|
+
end
|
444
|
+
|
445
|
+
it 'should set the last modified on the feed' do
|
446
|
+
@new_feed.should_receive(:last_modified=).with('Wed, 28 Jan 2009 04:10:32 GMT')
|
447
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
448
|
+
@easy_curl.on_success.call(@easy_curl)
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'should add the feed to the responses' do
|
452
|
+
responses = {}
|
453
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], responses, {})
|
454
|
+
@easy_curl.on_success.call(@easy_curl)
|
455
|
+
|
456
|
+
responses.length.should == 1
|
457
|
+
responses['http://feeds.feedburner.com/PaulDixExplainsNothing'].should == @feed
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'should call proc if :on_success option is passed' do
|
461
|
+
success = lambda { |feed| }
|
462
|
+
success.should_receive(:call).with(@feed)
|
463
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
|
464
|
+
@easy_curl.on_success.call(@easy_curl)
|
465
|
+
end
|
466
|
+
|
467
|
+
it 'should call update from feed on the old feed with the updated feed' do
|
468
|
+
@feed.should_receive(:update_from_feed).with(@new_feed)
|
469
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, {})
|
470
|
+
@easy_curl.on_success.call(@easy_curl)
|
236
471
|
end
|
237
|
-
|
238
|
-
|
239
|
-
|
472
|
+
end
|
473
|
+
|
474
|
+
describe 'on failure' do
|
475
|
+
before(:each) do
|
476
|
+
@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"
|
477
|
+
@body = 'Page could not be found.'
|
478
|
+
|
479
|
+
@easy_curl.stub!(:response_code).and_return(404)
|
480
|
+
@easy_curl.stub!(:header_str).and_return(@headers)
|
481
|
+
@easy_curl.stub!(:body_str).and_return(@body)
|
482
|
+
end
|
483
|
+
|
484
|
+
it 'should call on success callback if the response code is 304' do
|
485
|
+
success = lambda { |feed| }
|
486
|
+
success.should_receive(:call).with(@feed)
|
487
|
+
@easy_curl.should_receive(:response_code).and_return(304)
|
488
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], {}, { :on_success => success })
|
489
|
+
@easy_curl.on_failure.call(@easy_curl)
|
490
|
+
end
|
491
|
+
|
492
|
+
it 'should return the http code in the responses' do
|
493
|
+
responses = {}
|
494
|
+
Feedzirra::Feed.add_feed_to_multi(@multi, @feed, [], responses, {})
|
495
|
+
@easy_curl.on_failure.call(@easy_curl)
|
496
|
+
|
497
|
+
responses.length.should == 1
|
498
|
+
responses['http://www.pauldix.net/'].should == 404
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
describe "#fetch_and_parse" do
|
504
|
+
it 'should initiate the fetching and parsing using multicurl'
|
505
|
+
it "should pass any request options through to add_url_to_multi"
|
506
|
+
it 'should slice the feeds into groups of thirty for processing'
|
507
|
+
it "should return a feed object if a single feed is passed in"
|
508
|
+
it "should return an return an array of feed objects if multiple feeds are passed in"
|
509
|
+
end
|
510
|
+
|
511
|
+
describe "#decode_content" do
|
512
|
+
before(:each) do
|
513
|
+
@curl_easy = mock('curl_easy', :body_str => '<xml></xml>')
|
514
|
+
end
|
515
|
+
|
516
|
+
it 'should decode the response body using gzip if the Content-Encoding: is gzip' do
|
517
|
+
@curl_easy.stub!(:header_str).and_return('Content-Encoding: gzip')
|
518
|
+
string_io = mock('stringio', :read => @curl_easy.body_str, :close => true)
|
519
|
+
StringIO.should_receive(:new).and_return(string_io)
|
520
|
+
Zlib::GzipReader.should_receive(:new).with(string_io).and_return(string_io)
|
521
|
+
Feedzirra::Feed.decode_content(@curl_easy)
|
240
522
|
end
|
241
523
|
|
242
|
-
it
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
updated_feeds.first.should_not be_updated
|
247
|
-
updated_feeds.last.should_not be_updated
|
524
|
+
it 'should deflate the response body using inflate if the Content-Encoding: is deflate' do
|
525
|
+
@curl_easy.stub!(:header_str).and_return('Content-Encoding: deflate')
|
526
|
+
Zlib::Deflate.should_receive(:inflate).with(@curl_easy.body_str)
|
527
|
+
Feedzirra::Feed.decode_content(@curl_easy)
|
248
528
|
end
|
529
|
+
|
530
|
+
it 'should return the response body if it is not encoded' do
|
531
|
+
@curl_easy.stub!(:header_str).and_return('')
|
532
|
+
Feedzirra::Feed.decode_content(@curl_easy).should == '<xml></xml>'
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
describe "#update" do
|
537
|
+
it 'should perform the updating using multicurl'
|
538
|
+
it "should pass any request options through to add_feed_to_multi"
|
539
|
+
it "should return a feed object if a single feed is passed in"
|
540
|
+
it "should return an return an array of feed objects if multiple feeds are passed in"
|
249
541
|
end
|
250
542
|
end
|
251
543
|
end
|