techthumb-feedzirra 0.0.1
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 +165 -0
- data/Rakefile +14 -0
- data/lib/core_ext/date.rb +21 -0
- data/lib/feedzirra/atom.rb +14 -0
- data/lib/feedzirra/atom_entry.rb +13 -0
- data/lib/feedzirra/atom_feed_burner.rb +14 -0
- data/lib/feedzirra/atom_feed_burner_entry.rb +12 -0
- data/lib/feedzirra/feed.rb +157 -0
- data/lib/feedzirra/feed_entry_utilities.rb +15 -0
- data/lib/feedzirra/feed_utilities.rb +62 -0
- data/lib/feedzirra/rdf.rb +15 -0
- data/lib/feedzirra/rdf_entry.rb +12 -0
- data/lib/feedzirra/rss.rb +15 -0
- data/lib/feedzirra/rss_entry.rb +15 -0
- data/lib/feedzirra.rb +29 -0
- data/spec/feedzirra/atom_entry_spec.rb +33 -0
- data/spec/feedzirra/atom_feed_burner_entry_spec.rb +33 -0
- data/spec/feedzirra/atom_feed_burner_spec.rb +39 -0
- data/spec/feedzirra/atom_spec.rb +35 -0
- data/spec/feedzirra/feed_entry_utilities_spec.rb +17 -0
- data/spec/feedzirra/feed_spec.rb +241 -0
- data/spec/feedzirra/feed_utilities_spec.rb +149 -0
- data/spec/feedzirra/rdf_entry_spec.rb +33 -0
- data/spec/feedzirra/rdf_spec.rb +37 -0
- data/spec/feedzirra/rss_entry_spec.rb +33 -0
- data/spec/feedzirra/rss_spec.rb +40 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +46 -0
- metadata +115 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::AtomFeedBurner do
|
4
|
+
describe "#will_parse?" do
|
5
|
+
it "should return true for a feedburner atom feed" do
|
6
|
+
Feedzirra::AtomFeedBurner.should be_able_to_parse(sample_feedburner_atom_feed)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return false for an rdf feed" do
|
10
|
+
Feedzirra::AtomFeedBurner.should_not be_able_to_parse(sample_rdf_feed)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return false for a regular atom feed" do
|
14
|
+
Feedzirra::AtomFeedBurner.should_not be_able_to_parse(sample_atom_feed)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "parsing" do
|
19
|
+
before(:each) do
|
20
|
+
@feed = Feedzirra::AtomFeedBurner.parse(sample_feedburner_atom_feed)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse the title" do
|
24
|
+
@feed.title.should == "Paul Dix Explains Nothing"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse the url" do
|
28
|
+
@feed.url.should == "http://www.pauldix.net/"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse the feed_url" do
|
32
|
+
@feed.feed_url.should == "http://feeds.feedburner.com/PaulDixExplainsNothing"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should parse entries" do
|
36
|
+
@feed.entries.size.should == 5
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::Atom do
|
4
|
+
describe "#will_parse?" do
|
5
|
+
it "should return true for an atom feed" do
|
6
|
+
Feedzirra::Atom.should be_able_to_parse(sample_atom_feed)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return false for an rdf feed" do
|
10
|
+
Feedzirra::Atom.should_not be_able_to_parse(sample_rdf_feed)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "parsing" do
|
15
|
+
before(:each) do
|
16
|
+
@feed = Feedzirra::Atom.parse(sample_atom_feed)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should parse the title" do
|
20
|
+
@feed.title.should == "Amazon Web Services Blog"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse the url" do
|
24
|
+
@feed.url.should == "http://aws.typepad.com/aws/"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse the feed_url" do
|
28
|
+
@feed.feed_url.should == "http://aws.typepad.com/aws/atom.xml"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse entries" do
|
32
|
+
@feed.entries.size.should == 10
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::FeedUtilities do
|
4
|
+
before(:each) do
|
5
|
+
@klass = Class.new do
|
6
|
+
include Feedzirra::FeedEntryUtilities
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "handling dates" do
|
11
|
+
it "should parse an ISO 8601 formatted datetime into Time" do
|
12
|
+
time = @klass.new.parse_datetime("2008-02-20T8:05:00-010:00")
|
13
|
+
time.class.should == Time
|
14
|
+
time.to_s.should == "Wed Feb 20 18:05:00 UTC 2008"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::Feed do
|
4
|
+
describe "#parse" do # many of these tests are redundant with the specific feed type tests, but I put them here for completeness
|
5
|
+
context "when there's an available parser" do
|
6
|
+
it "should parse an rdf feed" do
|
7
|
+
feed = Feedzirra::Feed.parse(sample_rdf_feed)
|
8
|
+
feed.title.should == "HREF Considered Harmful"
|
9
|
+
feed.entries.first.published.to_s.should == "Tue Sep 02 19:50:07 UTC 2008"
|
10
|
+
feed.entries.size.should == 10
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should parse an rss feed" do
|
14
|
+
feed = Feedzirra::Feed.parse(sample_rss_feed)
|
15
|
+
feed.title.should == "Tender Lovemaking"
|
16
|
+
feed.entries.first.published.to_s.should == "Thu Dec 04 17:17:49 UTC 2008"
|
17
|
+
feed.entries.size.should == 10
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should parse an atom feed" do
|
21
|
+
feed = Feedzirra::Feed.parse(sample_atom_feed)
|
22
|
+
feed.title.should == "Amazon Web Services Blog"
|
23
|
+
feed.entries.first.published.to_s.should == "Fri Jan 16 18:21:00 UTC 2009"
|
24
|
+
feed.entries.size.should == 10
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse an feedburner atom feed" do
|
28
|
+
feed = Feedzirra::Feed.parse(sample_feedburner_atom_feed)
|
29
|
+
feed.title.should == "Paul Dix Explains Nothing"
|
30
|
+
feed.entries.first.published.to_s.should == "Thu Jan 22 15:50:22 UTC 2009"
|
31
|
+
feed.entries.size.should == 5
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when there's no available parser" do
|
36
|
+
it "raises Feedzirra::NoParserAvailable" do
|
37
|
+
proc {
|
38
|
+
Feedzirra::Feed.parse("I'm an invalid feed")
|
39
|
+
}.should raise_error(Feedzirra::NoParserAvailable)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should parse an feedburner rss feed" do
|
44
|
+
feed = Feedzirra::Feed.parse(sample_rss_feed_burner_feed)
|
45
|
+
feed.title.should == "Sam Harris: Author, Philosopher, Essayist, Atheist"
|
46
|
+
feed.entries.first.published.to_s.should == "Tue Jan 13 17:20:28 UTC 2009"
|
47
|
+
feed.entries.size.should == 10
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#determine_feed_parser_for_xml" do
|
52
|
+
it "should return the Feedzirra::Atom class for an atom feed" do
|
53
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(sample_atom_feed).should == Feedzirra::Atom
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return the Feedzirra::AtomFeedBurner class for an atom feedburner feed" do
|
57
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(sample_feedburner_atom_feed).should == Feedzirra::AtomFeedBurner
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return the Feedzirra::RSS class for an rdf/rss 1.0 feed" do
|
61
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rdf_feed).should == Feedzirra::RSS
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return the Feedzirra::RSS class for an rss feedburner feed" do
|
65
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed_burner_feed).should == Feedzirra::RSS
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return the Feedzirra::RSS object for an rss 2.0 feed" do
|
69
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(sample_rss_feed).should == Feedzirra::RSS
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "adding feed types" do
|
74
|
+
it "should prioritize added feed types over the built in ones" do
|
75
|
+
feed_text = "Atom asdf"
|
76
|
+
Feedzirra::Atom.should be_able_to_parse(feed_text)
|
77
|
+
new_feed_type = Class.new do
|
78
|
+
def self.able_to_parse?(val)
|
79
|
+
true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
new_feed_type.should be_able_to_parse(feed_text)
|
83
|
+
Feedzirra::Feed.add_feed_class(new_feed_type)
|
84
|
+
Feedzirra::Feed.determine_feed_parser_for_xml(feed_text).should == new_feed_type
|
85
|
+
|
86
|
+
# this is a hack so that this doesn't break the rest of the tests
|
87
|
+
Feedzirra::Feed.feed_classes.reject! {|o| o == new_feed_type }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "header parsing" do
|
92
|
+
before(:each) do
|
93
|
+
@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
|
+
end
|
95
|
+
|
96
|
+
it "should parse out an etag" do
|
97
|
+
Feedzirra::Feed.etag_from_header(@header).should == "ziEyTl4q9GH04BR4jgkImd0GvSE"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should return nil if there is no etag in header" do
|
101
|
+
Feedzirra::Feed.etag_from_header("foo").should be_nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should parse out a last-modified date" do
|
105
|
+
Feedzirra::Feed.last_modified_from_header(@header).should == Time.parse("Wed, 28 Jan 2009 04:10:32 GMT")
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should return nil if there is no last-modified in header" do
|
109
|
+
Feedzirra::Feed.last_modified_from_header("foo").should be_nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "fetching feeds" do
|
114
|
+
before(:each) do
|
115
|
+
@paul_feed_url = "http://feeds.feedburner.com/PaulDixExplainsNothing"
|
116
|
+
@trotter_feed_url = "http://feeds.feedburner.com/trottercashion"
|
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)"
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#fetch_raw" do
|
125
|
+
it "should take :user_agent as an option"
|
126
|
+
it "should take :if_modified_since as an option"
|
127
|
+
it "should take :if_none_match as an option"
|
128
|
+
it "should take an optional on_success lambda"
|
129
|
+
it "should take an optional on_failure lambda"
|
130
|
+
|
131
|
+
it "should return raw xml" do
|
132
|
+
Feedzirra::Feed.fetch_raw(@paul_feed_url).should =~ /^#{Regexp.escape('<?xml version="1.0" encoding="UTF-8"?>')}/
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should take multiple feed urls and return a hash of urls and response xml" do
|
136
|
+
results = Feedzirra::Feed.fetch_raw([@paul_feed_url, @trotter_feed_url])
|
137
|
+
results.keys.should include(@paul_feed_url)
|
138
|
+
results.keys.should include(@trotter_feed_url)
|
139
|
+
results[@paul_feed_url].should =~ /Paul Dix/
|
140
|
+
results[@trotter_feed_url].should =~ /Trotter Cashion/
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#fetch_and_parse" do
|
145
|
+
it "should return a feed object for a single url" do
|
146
|
+
feed = Feedzirra::Feed.fetch_and_parse(@paul_feed_url)
|
147
|
+
feed.title.should == "Paul Dix Explains Nothing"
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should set the feed_url to the new url if redirected" do
|
151
|
+
feed = Feedzirra::Feed.fetch_and_parse("http://tinyurl.com/tenderlovemaking")
|
152
|
+
feed.feed_url.should == "http://tenderlovemaking.com/feed/"
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should set the feed_url for an rdf feed" do
|
156
|
+
feed = Feedzirra::Feed.fetch_and_parse("http://www.avibryant.com/rss.xml")
|
157
|
+
feed.feed_url.should == "http://www.avibryant.com/rss.xml"
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should set the feed_url for an rss feed" do
|
161
|
+
feed = Feedzirra::Feed.fetch_and_parse("http://tenderlovemaking.com/feed/")
|
162
|
+
feed.feed_url.should == "http://tenderlovemaking.com/feed/"
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should return a hash of feed objects with the passed in feed_url for the key and parsed feed for the value for multiple feeds" do
|
166
|
+
feeds = Feedzirra::Feed.fetch_and_parse([@paul_feed_url, @trotter_feed_url])
|
167
|
+
feeds.size.should == 2
|
168
|
+
feeds[@paul_feed_url].feed_url.should == @paul_feed_url
|
169
|
+
feeds[@trotter_feed_url].feed_url.should == @trotter_feed_url
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should yeild the url and feed object to a :on_success lambda" do
|
173
|
+
successful_call_mock = mock("successful_call_mock")
|
174
|
+
successful_call_mock.should_receive(:call)
|
175
|
+
Feedzirra::Feed.fetch_and_parse(@paul_feed_url, :on_success => lambda { |feed_url, feed|
|
176
|
+
feed_url.should == @paul_feed_url
|
177
|
+
feed.class.should == Feedzirra::AtomFeedBurner
|
178
|
+
successful_call_mock.call})
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should yield the url, response_code, response_header, and response_body to a :on_failure lambda" do
|
182
|
+
failure_call_mock = mock("failure_call_mock")
|
183
|
+
failure_call_mock.should_receive(:call)
|
184
|
+
fail_url = "http://localhost"
|
185
|
+
Feedzirra::Feed.fetch_and_parse(fail_url, :on_failure => lambda {|feed_url, response_code, response_header, response_body|
|
186
|
+
feed_url.should == fail_url
|
187
|
+
response_code.should == 0
|
188
|
+
response_header.should == ""
|
189
|
+
response_body.should == ""
|
190
|
+
failure_call_mock.call})
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should return a not modified status for a feed with a :if_modified_since is past its last update" do
|
194
|
+
Feedzirra::Feed.fetch_and_parse(@paul_feed_url, :if_modified_since => Time.now).should == 304
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should set the etag from the header" # do
|
198
|
+
# Feedzirra::Feed.fetch_and_parse(@paul_feed_url).etag.should_not == ""
|
199
|
+
# end
|
200
|
+
|
201
|
+
it "should set the last_modified from the header" # do
|
202
|
+
# Feedzirra::Feed.fetch_and_parse(@paul_feed_url).last_modified.should.class == Time
|
203
|
+
# end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#update" do
|
207
|
+
it "should update and return a single feed object" do
|
208
|
+
feed = Feedzirra::Feed.fetch_and_parse(@paul_feed_url)
|
209
|
+
feed.entries.delete_at(0)
|
210
|
+
feed.last_modified = nil
|
211
|
+
feed.etag = nil
|
212
|
+
updated_feed = Feedzirra::Feed.update(feed)
|
213
|
+
updated_feed.new_entries.size.should == 1
|
214
|
+
updated_feed.should have_new_entries
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should update a collection of feed objects" do
|
218
|
+
feeds = Feedzirra::Feed.fetch_and_parse([@paul_feed_url, @trotter_feed_url])
|
219
|
+
paul_entries_size = feeds[@paul_feed_url].entries.size
|
220
|
+
trotter_entries_size = feeds[@trotter_feed_url].entries.size
|
221
|
+
|
222
|
+
feeds.values.each do |feed|
|
223
|
+
feed.last_modified = nil
|
224
|
+
feed.etag = nil
|
225
|
+
feed.entries.delete_at(0)
|
226
|
+
end
|
227
|
+
updated_feeds = Feedzirra::Feed.update(feeds.values)
|
228
|
+
updated_feeds.detect {|f| f.feed_url == @paul_feed_url}.entries.size.should == paul_entries_size
|
229
|
+
updated_feeds.detect {|f| f.feed_url == @trotter_feed_url}.entries.size.should == trotter_entries_size
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should return the feed objects even when not updated" do
|
233
|
+
feeds = Feedzirra::Feed.fetch_and_parse([@paul_feed_url, @trotter_feed_url])
|
234
|
+
updated_feeds = Feedzirra::Feed.update(feeds.values)
|
235
|
+
updated_feeds.size.should == 2
|
236
|
+
updated_feeds.first.should_not be_updated
|
237
|
+
updated_feeds.last.should_not be_updated
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::FeedUtilities do
|
4
|
+
before(:each) do
|
5
|
+
@klass = Class.new do
|
6
|
+
include Feedzirra::FeedUtilities
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "instance methods" do
|
11
|
+
it "should provide an updated? accessor" do
|
12
|
+
feed = @klass.new
|
13
|
+
feed.should_not be_updated
|
14
|
+
feed.updated = true
|
15
|
+
feed.should be_updated
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should provide a new_entries accessor" do
|
19
|
+
feed = @klass.new
|
20
|
+
feed.new_entries.should == []
|
21
|
+
feed.new_entries = [:foo]
|
22
|
+
feed.new_entries.should == [:foo]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should provide an etag accessor" do
|
26
|
+
feed = @klass.new
|
27
|
+
feed.etag = "foo"
|
28
|
+
feed.etag.should == "foo"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should provide a last_modified accessor" do
|
32
|
+
feed = @klass.new
|
33
|
+
time = Time.now
|
34
|
+
feed.last_modified = time
|
35
|
+
feed.last_modified.should == time
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return new_entries? as true when entries are put into new_entries" do
|
39
|
+
feed = @klass.new
|
40
|
+
feed.new_entries << :foo
|
41
|
+
feed.should have_new_entries
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return a last_modified value from the entry with the most recent published date if the last_modified date hasn't been set" do
|
45
|
+
feed = Feedzirra::Atom.new
|
46
|
+
entry =Feedzirra::AtomEntry.new
|
47
|
+
entry.published = Time.now.to_s
|
48
|
+
feed.entries << entry
|
49
|
+
feed.last_modified.should == entry.published
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should not throw an error if one of the entries has published date of nil" do
|
53
|
+
feed = Feedzirra::Atom.new
|
54
|
+
entry = Feedzirra::AtomEntry.new
|
55
|
+
entry.published = Time.now.to_s
|
56
|
+
feed.entries << entry
|
57
|
+
feed.entries << Feedzirra::AtomEntry.new
|
58
|
+
feed.last_modified.should == entry.published
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#update_from_feed" do
|
63
|
+
describe "updating feed attributes" do
|
64
|
+
before(:each) do
|
65
|
+
# I'm using the Atom class when I know I should be using a different one. However, this update_from_feed
|
66
|
+
# method would only be called against a feed item.
|
67
|
+
@feed = Feedzirra::Atom.new
|
68
|
+
@feed.title = "A title"
|
69
|
+
@feed.url = "http://pauldix.net"
|
70
|
+
@feed.feed_url = "http://feeds.feedburner.com/PaulDixExplainsNothing"
|
71
|
+
@feed.updated = false
|
72
|
+
@updated_feed = @feed.dup
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should update the title if changed" do
|
76
|
+
@updated_feed.title = "new title"
|
77
|
+
@feed.update_from_feed(@updated_feed)
|
78
|
+
@feed.title.should == @updated_feed.title
|
79
|
+
@feed.should be_updated
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not update the title if the same" do
|
83
|
+
@feed.update_from_feed(@updated_feed)
|
84
|
+
@feed.should_not be_updated
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should update the feed_url if changed" do
|
88
|
+
@updated_feed.feed_url = "a new feed url"
|
89
|
+
@feed.update_from_feed(@updated_feed)
|
90
|
+
@feed.feed_url.should == @updated_feed.feed_url
|
91
|
+
@feed.should be_updated
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not update the feed_url if the same" do
|
95
|
+
@feed.update_from_feed(@updated_feed)
|
96
|
+
@feed.should_not be_updated
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should update the url if changed" do
|
100
|
+
@updated_feed.url = "a new url"
|
101
|
+
@feed.update_from_feed(@updated_feed)
|
102
|
+
@feed.url.should == @updated_feed.url
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should not update the url if not changed" do
|
106
|
+
@feed.update_from_feed(@updated_feed)
|
107
|
+
@feed.should_not be_updated
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "updating entries" do
|
112
|
+
before(:each) do
|
113
|
+
# I'm using the Atom class when I know I should be using a different one. However, this update_from_feed
|
114
|
+
# method would only be called against a feed item.
|
115
|
+
@feed = Feedzirra::Atom.new
|
116
|
+
@feed.title = "A title"
|
117
|
+
@feed.url = "http://pauldix.net"
|
118
|
+
@feed.feed_url = "http://feeds.feedburner.com/PaulDixExplainsNothing"
|
119
|
+
@feed.updated = false
|
120
|
+
@updated_feed = @feed.dup
|
121
|
+
@old_entry = Feedzirra::AtomEntry.new
|
122
|
+
@old_entry.url = "http://pauldix.net/old.html"
|
123
|
+
@old_entry.published = Time.now.to_s
|
124
|
+
@new_entry = Feedzirra::AtomEntry.new
|
125
|
+
@new_entry.url = "http://pauldix.net/new.html"
|
126
|
+
@new_entry.published = (Time.now + 10).to_s
|
127
|
+
@feed.entries << @old_entry
|
128
|
+
@updated_feed.entries << @new_entry
|
129
|
+
@updated_feed.entries << @old_entry
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should update last-modified from the latest entry date" do
|
133
|
+
@feed.update_from_feed(@updated_feed)
|
134
|
+
@feed.last_modified.should == @new_entry.published
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should put new entries into new_entries" do
|
138
|
+
@feed.update_from_feed(@updated_feed)
|
139
|
+
@feed.new_entries.should == [@new_entry]
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should also put new entries into the entries collection" do
|
143
|
+
@feed.update_from_feed(@updated_feed)
|
144
|
+
@feed.entries.should include(@new_entry)
|
145
|
+
@feed.entries.should include(@old_entry)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::RDFEntry do
|
4
|
+
before(:each) do
|
5
|
+
# I don't really like doing it this way because these unit test should only rely on AtomEntry,
|
6
|
+
# but this is actually how it should work. You would never just pass entry xml straight to the AtomEnry
|
7
|
+
@entry = Feedzirra::RDF.parse(sample_rdf_feed).entries.first
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse the title" do
|
11
|
+
@entry.title.should == "Chrome, V8 and Strongtalk"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should parse the url" do
|
15
|
+
@entry.url.should == "http://www.avibryant.com/2008/09/chrome-v8-and-s.html"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse the author" do
|
19
|
+
@entry.author.should == "Avi"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should parse the content" do
|
23
|
+
@entry.content.should == sample_rdf_entry_content
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should provide a summary" do
|
27
|
+
@entry.summary.should == "There's lots to like about Google's new web browser, Chrome, which was released today. When I read the awesome comic strip introduction yesterday, however, the thing that stood out most for me was in very small type: the name Lars..."
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should parse the published date" do
|
31
|
+
@entry.published.to_s.should == "Tue Sep 02 19:50:07 UTC 2008"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::RDF do
|
4
|
+
describe "#will_parse?" do
|
5
|
+
it "should return true for an rdf feed" do
|
6
|
+
Feedzirra::RDF.should be_able_to_parse(sample_rdf_feed)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return false for an atom feed" do
|
10
|
+
Feedzirra::RDF.should_not be_able_to_parse(sample_atom_feed)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "parsing" do
|
15
|
+
before(:each) do
|
16
|
+
@feed = Feedzirra::RDF.parse(sample_rdf_feed)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should parse the title" do
|
20
|
+
@feed.title.should == "HREF Considered Harmful"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse the url" do
|
24
|
+
@feed.url.should == "http://www.avibryant.com/"
|
25
|
+
end
|
26
|
+
|
27
|
+
# rdf doesn't actually specify the feed_url. This should be set in the fetcher.
|
28
|
+
it "should provide an accessor for the feed_url" do
|
29
|
+
@feed.respond_to?(:feed_url).should == true
|
30
|
+
@feed.respond_to?(:feed_url=).should == true
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should parse entries" do
|
34
|
+
@feed.entries.size.should == 10
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::RSSEntry do
|
4
|
+
before(:each) do
|
5
|
+
# I don't really like doing it this way because these unit test should only rely on RSSEntry,
|
6
|
+
# but this is actually how it should work. You would never just pass entry xml straight to the AtomEnry
|
7
|
+
@entry = Feedzirra::RSS.parse(sample_rss_feed).entries.first
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse the title" do
|
11
|
+
@entry.title.should == "Nokogiri’s Slop Feature"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should parse the url" do
|
15
|
+
@entry.url.should == "http://tenderlovemaking.com/2008/12/04/nokogiris-slop-feature/"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse the author" do
|
19
|
+
@entry.author.should == "Aaron Patterson"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should parse the content" do
|
23
|
+
@entry.content.should == sample_rss_entry_content
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should provide a summary" do
|
27
|
+
@entry.summary.should == "Oops! When I released nokogiri version 1.0.7, I totally forgot to talk about Nokogiri::Slop() feature that was added. Why is it called \"slop\"? It lets you sloppily explore documents. Basically, it decorates your document with method_missing() that allows you to search your document via method calls.\nGiven this document:\n\ndoc = Nokogiri::Slop(<<-eohtml)\n<html>\n  <body>\n  [...]"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should parse the published date" do
|
31
|
+
@entry.published.to_s.should == "Thu Dec 04 17:17:49 UTC 2008"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Feedzirra::RSS do
|
4
|
+
describe "#will_parse?" do
|
5
|
+
it "should return true for an RSS feed" do
|
6
|
+
Feedzirra::RSS.should be_able_to_parse(sample_rss_feed)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return false for an rdf feed" do
|
10
|
+
Feedzirra::RSS.should_not be_able_to_parse(sample_rdf_feed)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return fase for an atom feed" do
|
14
|
+
Feedzirra::RSS.should_not be_able_to_parse(sample_atom_feed)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "parsing" do
|
19
|
+
before(:each) do
|
20
|
+
@feed = Feedzirra::RSS.parse(sample_rss_feed)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse the title" do
|
24
|
+
@feed.title.should == "Tender Lovemaking"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse the url" do
|
28
|
+
@feed.url.should == "http://tenderlovemaking.com"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should provide an accessor for the feed_url" do
|
32
|
+
@feed.respond_to?(:feed_url).should == true
|
33
|
+
@feed.respond_to?(:feed_url=).should == true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should parse entries" do
|
37
|
+
@feed.entries.size.should == 10
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec"
|
3
|
+
|
4
|
+
# gem install redgreen for colored test output
|
5
|
+
begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
|
6
|
+
|
7
|
+
path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
8
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
9
|
+
|
10
|
+
require "lib/feedzirra"
|
11
|
+
|
12
|
+
def sample_atom_feed
|
13
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/AmazonWebServicesBlog.xml")
|
14
|
+
end
|
15
|
+
|
16
|
+
def sample_atom_entry_content
|
17
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/AmazonWebServicesBlogFirstEntryContent.xml")
|
18
|
+
end
|
19
|
+
|
20
|
+
def sample_rdf_feed
|
21
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/HREFConsideredHarmful.xml")
|
22
|
+
end
|
23
|
+
|
24
|
+
def sample_rdf_entry_content
|
25
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/HREFConsideredHarmfulFirstEntry.xml")
|
26
|
+
end
|
27
|
+
|
28
|
+
def sample_rss_feed_burner_feed
|
29
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/SamHarrisAuthorPhilosopherEssayistAtheist.xml")
|
30
|
+
end
|
31
|
+
|
32
|
+
def sample_rss_feed
|
33
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/TenderLovemaking.xml")
|
34
|
+
end
|
35
|
+
|
36
|
+
def sample_rss_entry_content
|
37
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/TenderLovemakingFirstEntry.xml")
|
38
|
+
end
|
39
|
+
|
40
|
+
def sample_feedburner_atom_feed
|
41
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/PaulDixExplainsNothing.xml")
|
42
|
+
end
|
43
|
+
|
44
|
+
def sample_feedburner_atom_entry_content
|
45
|
+
File.read("#{File.dirname(__FILE__)}/sample_feeds/PaulDixExplainsNothingFirstEntryContent.xml")
|
46
|
+
end
|