ratom 0.2.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.
Files changed (53) hide show
  1. data/History.txt +7 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +52 -0
  4. data/README.txt +123 -0
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +72 -0
  7. data/config/requirements.rb +17 -0
  8. data/lib/atom.rb +566 -0
  9. data/lib/atom/pub.rb +185 -0
  10. data/lib/atom/version.rb +9 -0
  11. data/lib/atom/xml/parser.rb +223 -0
  12. data/setup.rb +1585 -0
  13. data/spec/app/member_entry.atom +31 -0
  14. data/spec/app/service.xml +36 -0
  15. data/spec/atom/pub_spec.rb +289 -0
  16. data/spec/atom_spec.rb +1012 -0
  17. data/spec/conformance/baseuri.atom +19 -0
  18. data/spec/conformance/divtest.atom +32 -0
  19. data/spec/conformance/linktests.xml +93 -0
  20. data/spec/conformance/nondefaultnamespace-baseline.atom +25 -0
  21. data/spec/conformance/nondefaultnamespace-xhtml.atom +25 -0
  22. data/spec/conformance/nondefaultnamespace.atom +25 -0
  23. data/spec/conformance/ordertest.xml +112 -0
  24. data/spec/conformance/title/html-cdata.atom +22 -0
  25. data/spec/conformance/title/html-entity.atom +22 -0
  26. data/spec/conformance/title/html-ncr.atom +22 -0
  27. data/spec/conformance/title/text-cdata.atom +22 -0
  28. data/spec/conformance/title/text-entity.atom +21 -0
  29. data/spec/conformance/title/text-ncr.atom +21 -0
  30. data/spec/conformance/title/xhtml-entity.atom +21 -0
  31. data/spec/conformance/title/xhtml-ncr.atom +21 -0
  32. data/spec/conformance/unknown-namespace.atom +25 -0
  33. data/spec/conformance/xmlbase.atom +133 -0
  34. data/spec/fixtures/complex_single_entry.atom +45 -0
  35. data/spec/fixtures/created_entry.atom +31 -0
  36. data/spec/fixtures/entry.atom +30 -0
  37. data/spec/fixtures/multiple_entry.atom +0 -0
  38. data/spec/fixtures/simple_single_entry.atom +21 -0
  39. data/spec/paging/first_paged_feed.atom +21 -0
  40. data/spec/paging/last_paged_feed.atom +21 -0
  41. data/spec/paging/middle_paged_feed.atom +22 -0
  42. data/spec/spec.opts +2 -0
  43. data/spec/spec_helper.rb +24 -0
  44. data/tasks/deployment.rake +34 -0
  45. data/tasks/environment.rake +7 -0
  46. data/tasks/rspec.rake +15 -0
  47. data/tasks/website.rake +17 -0
  48. data/website/index.html +11 -0
  49. data/website/index.txt +39 -0
  50. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  51. data/website/stylesheets/screen.css +138 -0
  52. data/website/template.rhtml +48 -0
  53. metadata +126 -0
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" ?>
2
+ <entry xmlns="http://www.w3.org/2005/Atom">
3
+ <title>Atom draft-07 snapshot</title>
4
+ <link rel="alternate" type="text/html"
5
+ href="http://example.org/2005/04/02/atom"/>
6
+ <link rel="edit" href="http://example.org/member_entry.atom"/>
7
+ <link rel="enclosure" type="audio/mpeg" length="1337"
8
+ href="http://example.org/audio/ph34r_my_podcast.mp3"/>
9
+ <id>tag:example.org,2003:3.2397</id>
10
+ <updated>2005-07-31T12:29:29Z</updated>
11
+ <published>2003-12-13T08:29:29-04:00</published>
12
+ <author>
13
+ <name>Mark Pilgrim</name>
14
+ <uri>http://example.org/</uri>
15
+ <email>f8dy@example.com</email>
16
+ </author>
17
+ <contributor>
18
+ <name>Sam Ruby</name>
19
+ </contributor>
20
+ <contributor>
21
+ <name>Joe Gregorio</name>
22
+ </contributor>
23
+ <content type="xhtml" xml:lang="en"
24
+ xml:base="http://diveintomark.org/">
25
+ <div xmlns="http://www.w3.org/1999/xhtml">
26
+ <p>
27
+ <i>[Update: The Atom draft is finished.]</i>
28
+ </p>
29
+ </div>
30
+ </content>
31
+ </entry>
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" encoding='utf-8'?>
2
+ <service xmlns="http://www.w3.org/2007/app"
3
+ xmlns:atom="http://www.w3.org/2005/Atom">
4
+ <workspace>
5
+ <atom:title>Main Site</atom:title>
6
+ <collection
7
+ href="http://example.org/blog/main" >
8
+ <atom:title>My Blog Entries</atom:title>
9
+ <categories
10
+ href="http://example.com/cats/forMain.cats" />
11
+ </collection>
12
+ <collection
13
+ href="http://example.org/blog/pic" >
14
+ <atom:title>Pictures</atom:title>
15
+ <accept>image/png</accept>
16
+ <accept>image/jpeg</accept>
17
+ <accept>image/gif</accept>
18
+ </collection>
19
+ </workspace>
20
+ <workspace>
21
+ <atom:title>Sidebar Blog</atom:title>
22
+ <collection
23
+ href="http://example.org/sidebar/list" >
24
+ <atom:title>Remaindered Links</atom:title>
25
+ <accept>application/atom+xml;type=entry</accept>
26
+ <categories fixed="yes">
27
+ <atom:category
28
+ scheme="http://example.org/extra-cats/"
29
+ term="joke" />
30
+ <atom:category
31
+ scheme="http://example.org/extra-cats/"
32
+ term="serious" />
33
+ </categories>
34
+ </collection>
35
+ </workspace>
36
+ </service>
@@ -0,0 +1,289 @@
1
+ # Copyright (c) 2008 The Kaphan Foundation
2
+ #
3
+ # Possession of a copy of this file grants no permission or license
4
+ # to use, modify, or create derivate works.
5
+ # Please contact info@peerworks.org for further information.
6
+ #
7
+
8
+ require File.dirname(__FILE__) + '/../spec_helper'
9
+ require 'atom'
10
+ require 'atom/pub'
11
+ require 'atom/version'
12
+ require 'uri'
13
+ require 'net/http'
14
+
15
+ describe Atom::Pub do
16
+ describe Atom::Pub::Service do
17
+ before(:all) do
18
+ @service = Atom::Pub::Service.load_service(File.open('spec/app/service.xml'))
19
+ end
20
+
21
+ it "should have 2 workspaces" do
22
+ @service.should have(2).workspaces
23
+ end
24
+
25
+ describe 'workspace 1' do
26
+ before(:each) do
27
+ @workspace = @service.workspaces.first
28
+ end
29
+
30
+ it "should have a title" do
31
+ @workspace.title.should == "Main Site"
32
+ end
33
+
34
+ it "should have 2 collections" do
35
+ @workspace.should have(2).collections
36
+ end
37
+
38
+ describe 'first collection' do
39
+ before(:each) do
40
+ @collection = @workspace.collections.first
41
+ end
42
+
43
+ it "should have the right href" do
44
+ @collection.href.should == 'http://example.org/blog/main'
45
+ end
46
+
47
+ it "should have categories" do
48
+ @collection.categories.should_not be_nil
49
+ end
50
+
51
+ it "should have a title" do
52
+ @collection.title.should == 'My Blog Entries'
53
+ end
54
+ end
55
+
56
+ describe 'second collection' do
57
+ before(:each) do
58
+ @collection = @workspace.collections[1]
59
+ end
60
+
61
+ it "should have a title" do
62
+ @collection.title.should == 'Pictures'
63
+ end
64
+
65
+ it "should have the right href" do
66
+ @collection.href.should == 'http://example.org/blog/pic'
67
+ end
68
+
69
+ it "should not have categories" do
70
+ @collection.categories.should be_nil
71
+ end
72
+
73
+ it "should have 3 accepts" do
74
+ @collection.should have(3).accepts
75
+ end
76
+
77
+ it "should accept 'image/png'" do
78
+ @collection.accepts.should include('image/png')
79
+ end
80
+
81
+ it "should accept 'image/jpeg'" do
82
+ @collection.accepts.should include('image/jpeg')
83
+ end
84
+
85
+ it "should accept 'image/gif'" do
86
+ @collection.accepts.should include('image/gif')
87
+ end
88
+ end
89
+ end
90
+
91
+ describe 'workspace 2' do
92
+ before(:each) do
93
+ @workspace = @service.workspaces[1]
94
+ end
95
+
96
+ it "should have a title" do
97
+ @workspace.title.should == 'Sidebar Blog'
98
+ end
99
+
100
+ it "should have 1 collection" do
101
+ @workspace.should have(1).collections
102
+ end
103
+
104
+ describe 'collection' do
105
+ before(:each) do
106
+ @collection = @workspace.collections.first
107
+ end
108
+
109
+ it "should have a title" do
110
+ @collection.title.should == 'Remaindered Links'
111
+ end
112
+
113
+ it "should have 1 accept" do
114
+ @collection.should have(1).accepts
115
+ end
116
+
117
+ it "should accept 'application/atom+xml;type=entry'" do
118
+ @collection.accepts.should include('application/atom+xml;type=entry')
119
+ end
120
+
121
+ it "should have categories" do
122
+ @collection.categories.should_not be_nil
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ describe Atom::Pub::Service do
129
+ it "should load from a URL" do
130
+ uri = URI.parse('http://example.com/service.xml')
131
+ response = Net::HTTPSuccess.new(nil, nil, nil)
132
+ response.stub!(:body).and_return(File.read('spec/app/service.xml'))
133
+ Net::HTTP.should_receive(:get_response).with(uri).and_return(response)
134
+ Atom::Pub::Service.load_service(uri).should be_an_instance_of(Atom::Pub::Service)
135
+ end
136
+
137
+ it "should raise ArgumentError with a non-http URL" do
138
+ lambda { Atom::Pub::Service.load_service(URI.parse('file:/tmp')) }.should raise_error(ArgumentError)
139
+ end
140
+ end
141
+
142
+ describe Atom::Pub::Collection do
143
+ before(:each) do
144
+ @collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
145
+ @request_headers = {'Accept' => 'application/atom+xml',
146
+ 'Content-Type' => 'application/atom+xml;type=entry',
147
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
148
+ }
149
+ end
150
+
151
+ it "should set the href from the hash" do
152
+ @collection.href.should == 'http://example.org/blog'
153
+ end
154
+
155
+ it "should return the feed" do
156
+ response = Net::HTTPSuccess.new(nil, nil, nil)
157
+ response.stub!(:body).and_return(File.read('spec/fixtures/simple_single_entry.atom'))
158
+ Net::HTTP.should_receive(:get_response).with(URI.parse(@collection.href)).and_return(response)
159
+ @collection.feed.should be_an_instance_of(Atom::Feed)
160
+ end
161
+
162
+ it "should send a POST request when an entry is published" do
163
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
164
+
165
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
166
+
167
+ http = mock('http')
168
+ http.should_receive(:post).with('/blog', entry.to_xml.to_s, @request_headers).and_return(response)
169
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
170
+
171
+ created = @collection.publish(entry)
172
+ created.should == entry
173
+ end
174
+
175
+ it "should behave well when no content is returned" do
176
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
177
+
178
+ response = mock_response(Net::HTTPCreated, " ")
179
+
180
+ http = mock('http')
181
+ http.should_receive(:post).with('/blog', entry.to_xml.to_s, @request_headers).and_return(response)
182
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
183
+
184
+ created = @collection.publish(entry)
185
+ created.should == entry
186
+ end
187
+
188
+ it "should raise error when response is not HTTPCreated" do
189
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
190
+ response = mock_response(Net::HTTPPreconditionFailed, "")
191
+
192
+ http = mock('http')
193
+ http.should_receive(:post).with('/blog', entry.to_xml.to_s, @request_headers).and_return(response)
194
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
195
+
196
+ lambda { @collection.publish(entry) }.should raise_error(Atom::Pub::ProtocolError)
197
+ end
198
+
199
+ it "should copy Location into edit link of entry" do
200
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
201
+
202
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s, 'Location' => 'http://example.org/edit/entry1.atom')
203
+
204
+ http = mock('http')
205
+ http.should_receive(:post).with('/blog', entry.to_xml.to_s, @request_headers).and_return(response)
206
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
207
+
208
+ created = @collection.publish(entry)
209
+ created.edit_link.should_not be_nil
210
+ created.edit_link.href.should == 'http://example.org/edit/entry1.atom'
211
+ end
212
+
213
+ it "should update the entry when response is different" do
214
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
215
+ response = mock_response(Net::HTTPCreated, File.read('spec/fixtures/created_entry.atom'),
216
+ 'Location' => 'http://example.org/edit/atom')
217
+
218
+ http = mock('http')
219
+ http.should_receive(:post).with('/blog', entry.to_xml.to_s, @request_headers).and_return(response)
220
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
221
+
222
+ created = @collection.publish(entry)
223
+ created.should == Atom::Entry.load_entry(File.open('spec/fixtures/created_entry.atom'))
224
+ end
225
+ end
226
+
227
+ describe Atom::Entry do
228
+ before(:each) do
229
+ @request_headers = {'Accept' => 'application/atom+xml',
230
+ 'Content-Type' => 'application/atom+xml;type=entry',
231
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
232
+ }
233
+ end
234
+
235
+ it "should send a PUT to the edit link on save!" do
236
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
237
+ response = mock_response(Net::HTTPSuccess, nil)
238
+
239
+ http = mock('http')
240
+ http.should_receive(:put).with('/member_entry.atom', entry.to_xml, @request_headers).and_return(response)
241
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
242
+
243
+ entry.save!
244
+ end
245
+
246
+ it "should send a DELETE to the edit link on delete!" do
247
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
248
+ response = mock_response(Net::HTTPSuccess, nil)
249
+
250
+ http = mock('http')
251
+ http.should_receive(:delete).with('/member_entry.atom', an_instance_of(Hash)).and_return(response)
252
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
253
+
254
+ entry.destroy!
255
+ end
256
+
257
+ it "should raise exception on save! without an edit link" do
258
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
259
+ lambda { entry.save! }.should raise_error(Atom::Pub::NotSupported)
260
+ end
261
+
262
+ it "should raise exception on save failure" do
263
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
264
+ response = mock_response(Net::HTTPClientError, nil)
265
+
266
+ http = mock('http')
267
+ http.should_receive(:put).with('/member_entry.atom', entry.to_xml, @request_headers).and_return(response)
268
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
269
+
270
+ lambda { entry.save! }.should raise_error(Atom::Pub::ProtocolError)
271
+ end
272
+
273
+ it "should raise exception on destroy! without an edit link" do
274
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
275
+ lambda { entry.destroy! }.should raise_error(Atom::Pub::NotSupported)
276
+ end
277
+
278
+ it "should raise exception on destroy failure" do
279
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
280
+ response = mock_response(Net::HTTPClientError, nil)
281
+
282
+ http = mock('http')
283
+ http.should_receive(:delete).with('/member_entry.atom', an_instance_of(Hash)).and_return(response)
284
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
285
+
286
+ lambda { entry.destroy! }.should raise_error(Atom::Pub::ProtocolError)
287
+ end
288
+ end
289
+ end
data/spec/atom_spec.rb ADDED
@@ -0,0 +1,1012 @@
1
+ # Copyright (c) 2008 The Kaphan Foundation
2
+ #
3
+ # Possession of a copy of this file grants no permission or license
4
+ # to use, modify, or create derivate works.
5
+ # Please contact info@peerworks.org for further information.
6
+ #
7
+
8
+ require File.dirname(__FILE__) + '/spec_helper.rb'
9
+ require 'net/http'
10
+
11
+ describe Atom do
12
+ describe "Atom::Feed.load_feed" do
13
+ it "should accept an IO" do
14
+ lambda { Atom::Feed.load_feed(File.open('spec/fixtures/simple_single_entry.atom')) }.should_not raise_error
15
+ end
16
+
17
+ it "should raise ArgumentError with something other than IO or URI" do
18
+ lambda { Atom::Feed.load_feed(nil) }.should raise_error(ArgumentError)
19
+ end
20
+
21
+ it "should accept a String" do
22
+ Atom::Feed.load_feed(File.read('spec/fixtures/simple_single_entry.atom')).should be_an_instance_of(Atom::Feed)
23
+ end
24
+
25
+ it "should accept a URI" do
26
+ uri = URI.parse('http://example.com/feed.atom')
27
+ response = Net::HTTPSuccess.new(nil, nil, nil)
28
+ response.stub!(:body).and_return(File.read('spec/fixtures/simple_single_entry.atom'))
29
+ Net::HTTP.should_receive(:get_response).with(uri).and_return(response)
30
+ Atom::Feed.load_feed(uri).should be_an_instance_of(Atom::Feed)
31
+ end
32
+
33
+ it "should raise ArgumentError with non-http uri" do
34
+ uri = URI.parse('file:/tmp')
35
+ lambda { Atom::Feed.load_feed(uri) }.should raise_error(ArgumentError)
36
+ end
37
+
38
+ it "should return an Atom::Feed" do
39
+ feed = Atom::Feed.load_feed(File.open('spec/fixtures/simple_single_entry.atom'))
40
+ feed.should be_an_instance_of(Atom::Feed)
41
+ end
42
+ end
43
+
44
+ describe 'Atom::Entry.load_entry' do
45
+ it "should accept an IO" do
46
+ Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom')).should be_an_instance_of(Atom::Entry)
47
+ end
48
+
49
+ it "should accept a URI" do
50
+ uri = URI.parse('http://example.org/')
51
+ response = Net::HTTPSuccess.new(nil, nil, nil)
52
+ response.stub!(:body).and_return(File.read('spec/fixtures/entry.atom'))
53
+ Net::HTTP.should_receive(:get_response).with(uri).and_return(response)
54
+ Atom::Entry.load_entry(uri).should be_an_instance_of(Atom::Entry)
55
+ end
56
+
57
+ it "should accept a String" do
58
+ Atom::Entry.load_entry(File.read('spec/fixtures/entry.atom')).should be_an_instance_of(Atom::Entry)
59
+ end
60
+
61
+ it "should raise ArgumentError with something other than IO, String or URI" do
62
+ lambda { Atom::Entry.load_entry(nil) }.should raise_error(ArgumentError)
63
+ end
64
+
65
+ it "should raise ArgumentError with non-http uri" do
66
+ lambda { Atom::Entry.load_entry(URI.parse('file:/tmp')) }.should raise_error(ArgumentError)
67
+ end
68
+ end
69
+
70
+ describe 'SimpleSingleFeed' do
71
+ before(:all) do
72
+ @feed = Atom::Feed.load_feed(File.open('spec/fixtures/simple_single_entry.atom'))
73
+ end
74
+
75
+ describe Atom::Feed do
76
+ it "should parse title" do
77
+ @feed.title.should == 'Example Feed'
78
+ end
79
+
80
+ it "should parse updated" do
81
+ @feed.updated.should == Time.parse('2003-12-13T18:30:02Z')
82
+ end
83
+
84
+ it "should parse id" do
85
+ @feed.id.should == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6'
86
+ end
87
+
88
+ it "should have an entries array" do
89
+ @feed.entries.should be_an_instance_of(Array)
90
+ end
91
+
92
+ it "should have one element in the entries array" do
93
+ @feed.entries.size.should == 1
94
+ end
95
+
96
+ it "should have an alternate" do
97
+ @feed.alternate.should_not be_nil
98
+ end
99
+
100
+ it "should have an Atom::Link as the alternate" do
101
+ @feed.alternate.should be_an_instance_of(Atom::Link)
102
+ end
103
+
104
+ it "should have the correct href in the alternate" do
105
+ @feed.alternate.href.should == 'http://example.org/'
106
+ end
107
+ end
108
+
109
+ describe Atom::Entry do
110
+ before(:each) do
111
+ @entry = @feed.entries.first
112
+ end
113
+
114
+ it "should parse title" do
115
+ @entry.title.should == 'Atom-Powered Robots Run Amok'
116
+ end
117
+
118
+ it "should have an alternate" do
119
+ @entry.alternate.should_not be_nil
120
+ end
121
+
122
+ it "should have an Atom::Link as the alternate" do
123
+ @entry.alternate.should be_an_instance_of(Atom::Link)
124
+ end
125
+
126
+ it "should have the correct href on the alternate" do
127
+ @entry.alternate.href.should == 'http://example.org/2003/12/13/atom03'
128
+ end
129
+
130
+ it "should parse id" do
131
+ @entry.id.should == 'urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a'
132
+ end
133
+
134
+ it "should parse updated" do
135
+ @entry.updated.should == Time.parse('2003-12-13T18:30:02Z')
136
+ end
137
+
138
+ it "should parse summary" do
139
+ @entry.summary.should == 'Some text.'
140
+ end
141
+
142
+ it "should parse content" do
143
+ @entry.content.should == 'This <em>is</em> html.'
144
+ end
145
+
146
+ it "should parse content type" do
147
+ @entry.content.type.should == 'html'
148
+ end
149
+ end
150
+ end
151
+
152
+ describe 'ComplexFeed' do
153
+ before(:all) do
154
+ @feed = Atom::Feed.load_feed(File.open('spec/fixtures/complex_single_entry.atom'))
155
+ end
156
+
157
+ describe Atom::Feed do
158
+ it "should have a title" do
159
+ @feed.title.should == 'dive into mark'
160
+ end
161
+
162
+ it "should have type on the title" do
163
+ @feed.title.type.should == 'text'
164
+ end
165
+
166
+ it "should have a subtitle" do
167
+ @feed.subtitle.should == 'A <em>lot</em> of effort went into making this effortless'
168
+ end
169
+
170
+ it "should have a type for the subtitle" do
171
+ @feed.subtitle.type.should == 'html'
172
+ end
173
+
174
+ it "should have an updated date" do
175
+ @feed.updated.should == Time.parse('2005-07-31T12:29:29Z')
176
+ end
177
+
178
+ it "should have an id" do
179
+ @feed.id.should == 'tag:example.org,2003:3'
180
+ end
181
+
182
+ it "should have 2 links" do
183
+ @feed.should have(2).links
184
+ end
185
+
186
+ it "should have an alternate link" do
187
+ @feed.alternate.should_not be_nil
188
+ end
189
+
190
+ it "should have the right url for the alternate" do
191
+ @feed.alternate.to_s.should == 'http://example.org/'
192
+ end
193
+
194
+ it "should have a self link" do
195
+ @feed.self.should_not be_nil
196
+ end
197
+
198
+ it "should have the right url for self" do
199
+ @feed.self.to_s.should == 'http://example.org/feed.atom'
200
+ end
201
+
202
+ it "should have rights" do
203
+ @feed.rights.should == 'Copyright (c) 2003, Mark Pilgrim'
204
+ end
205
+
206
+ it "should have a generator" do
207
+ @feed.generator.should_not be_nil
208
+ end
209
+
210
+ it "should have a generator uri" do
211
+ @feed.generator.uri.should == 'http://www.example.com/'
212
+ end
213
+
214
+ it "should have a generator version" do
215
+ @feed.generator.version.should == '1.0'
216
+ end
217
+
218
+ it "should have a generator name" do
219
+ @feed.generator.name.should == 'Example Toolkit'
220
+ end
221
+
222
+ it "should have an entry" do
223
+ @feed.should have(1).entries
224
+ end
225
+ end
226
+
227
+ describe Atom::Entry do
228
+ before(:each) do
229
+ @entry = @feed.entries.first
230
+ end
231
+
232
+ it "should have a title" do
233
+ @entry.title.should == 'Atom draft-07 snapshot'
234
+ end
235
+
236
+ it "should have an id" do
237
+ @entry.id.should == 'tag:example.org,2003:3.2397'
238
+ end
239
+
240
+ it "should have an updated date" do
241
+ @entry.updated.should == Time.parse('2005-07-31T12:29:29Z')
242
+ end
243
+
244
+ it "should have a published date" do
245
+ @entry.published.should == Time.parse('2003-12-13T08:29:29-04:00')
246
+ end
247
+
248
+ it "should have an author" do
249
+ @entry.should have(1).authors
250
+ end
251
+
252
+ it "should have two links" do
253
+ @entry.should have(2).links
254
+ end
255
+
256
+ it "should have one alternate link" do
257
+ @entry.should have(1).alternates
258
+ end
259
+
260
+ it "should have one enclosure link" do
261
+ @entry.should have(1).enclosures
262
+ end
263
+
264
+ it "should have 2 contributors" do
265
+ @entry.should have(2).contributors
266
+ end
267
+
268
+ it "should have names for the contributors" do
269
+ @entry.contributors[0].name.should == 'Sam Ruby'
270
+ @entry.contributors[1].name.should == 'Joe Gregorio'
271
+ end
272
+
273
+ it "should have content" do
274
+ @entry.content.should_not be_nil
275
+ end
276
+ end
277
+
278
+ describe Atom::Link do
279
+ describe 'alternate link' do
280
+ before(:each) do
281
+ @entry = @feed.entries.first
282
+ @link = @entry.alternate
283
+ end
284
+
285
+ it "should have text/html type" do
286
+ @link.type.should == 'text/html'
287
+ end
288
+
289
+ it "should have alternate rel" do
290
+ @link.rel.should == 'alternate'
291
+ end
292
+
293
+ it "should have href 'http://example.org/2005/04/02/atom'" do
294
+ @link.href.should == 'http://example.org/2005/04/02/atom'
295
+ end
296
+
297
+ it "should have 'http://example.org/2005/04/02/atom' string representation" do
298
+ @link.to_s.should == 'http://example.org/2005/04/02/atom'
299
+ end
300
+ end
301
+
302
+ describe 'enclosure link' do
303
+ before(:each) do
304
+ @entry = @feed.entries.first
305
+ @link = @entry.enclosures.first
306
+ end
307
+
308
+ it "should have audio/mpeg type" do
309
+ @link.type.should == 'audio/mpeg'
310
+ end
311
+
312
+ it "should have enclosure rel" do
313
+ @link.rel.should == 'enclosure'
314
+ end
315
+
316
+ it "should have length 1337" do
317
+ @link.length.should == 1337
318
+ end
319
+
320
+ it "should have href 'http://example.org/audio/ph34r_my_podcast.mp3'" do
321
+ @link.href.should == 'http://example.org/audio/ph34r_my_podcast.mp3'
322
+ end
323
+
324
+ it "should have 'http://example.org/audio/ph34r_my_podcast.mp3' string representation" do
325
+ @link.to_s.should == 'http://example.org/audio/ph34r_my_podcast.mp3'
326
+ end
327
+ end
328
+ end
329
+
330
+ describe Atom::Person do
331
+ before(:each) do
332
+ @entry = @feed.entries.first
333
+ @person = @entry.authors.first
334
+ end
335
+
336
+ it "should have a name" do
337
+ @person.name.should == 'Mark Pilgrim'
338
+ end
339
+
340
+ it "should have a uri" do
341
+ @person.uri.should == 'http://example.org/'
342
+ end
343
+
344
+ it "should have an email address" do
345
+ @person.email.should == 'f8dy@example.com'
346
+ end
347
+ end
348
+
349
+ describe Atom::Content do
350
+ before(:each) do
351
+ @entry = @feed.entries.first
352
+ @content = @entry.content
353
+ end
354
+
355
+ it "should have 'xhtml' type" do
356
+ @content.type.should == 'xhtml'
357
+ end
358
+
359
+ it "should have 'en' language" do
360
+ @content.xml_lang.should == 'en'
361
+ end
362
+
363
+ it "should have the content as the string representation" do
364
+ @content.should == '<p xmlns="http://www.w3.org/1999/xhtml"><i>[Update: The Atom draft is finished.]</i></p>'
365
+ end
366
+ end
367
+ end
368
+
369
+ describe 'ConformanceTests' do
370
+ describe 'nondefaultnamespace.atom' do
371
+ before(:all) do
372
+ @feed = Atom::Feed.load_feed(File.open('spec/conformance/nondefaultnamespace.atom'))
373
+ end
374
+
375
+ it "should have a title" do
376
+ @feed.title.should == 'Non-default namespace test'
377
+ end
378
+
379
+ it "should have 1 entry" do
380
+ @feed.should have(1).entries
381
+ end
382
+
383
+ describe Atom::Entry do
384
+ before(:all) do
385
+ @entry = @feed.entries.first
386
+ end
387
+
388
+ it "should have a title" do
389
+ @entry.title.should == 'If you can read the content of this entry, your aggregator works fine.'
390
+ end
391
+
392
+ it "should have content" do
393
+ @entry.content.should_not be_nil
394
+ end
395
+
396
+ it "should have 'xhtml' for the type of the content" do
397
+ @entry.content.type.should == 'xhtml'
398
+ end
399
+
400
+ it "should strip the outer div of the content" do
401
+ @entry.content.should_not match(/div/)
402
+ end
403
+
404
+ it "should keep inner xhtml of content" do
405
+ @entry.content.should == '<p xmlns="http://www.w3.org/1999/xhtml">For information, see:</p> ' +
406
+ '<ul xmlns="http://www.w3.org/1999/xhtml"> ' +
407
+ '<li><a href="http://plasmasturm.org/log/376/">Who knows an <abbr title="Extensible Markup Language">XML</abbr> document from a hole in the ground?</a></li> ' +
408
+ '<li><a href="http://plasmasturm.org/log/377/">More on Atom aggregator <abbr title="Extensible Markup Language">XML</abbr> namespace conformance tests</a></li> ' +
409
+ '<li><a href="http://www.intertwingly.net/wiki/pie/XmlNamespaceConformanceTests"><abbr title="Extensible Markup Language">XML</abbr> Namespace Conformance Tests</a></li> ' +
410
+ '</ul>'
411
+ end
412
+ end
413
+ end
414
+
415
+ describe 'unknown-namespace.atom' do
416
+ before(:all) do
417
+ @feed = Atom::Feed.load_feed(File.open('spec/conformance/unknown-namespace.atom'))
418
+ @entry = @feed.entries.first
419
+ @content = @entry.content
420
+ end
421
+
422
+ it "should have content" do
423
+ @content.should_not be_nil
424
+ end
425
+
426
+ it "should strip surrounding div" do
427
+ @content.should_not match(/div/)
428
+ end
429
+
430
+ it "should keep inner lists" do
431
+ @content.should match(/<h:ul/)
432
+ @content.should match(/<ul/)
433
+ end
434
+
435
+ it "should have xhtml type" do
436
+ @content.type.should == 'xhtml'
437
+ end
438
+ end
439
+
440
+ describe 'linktests.atom' do
441
+ before(:all) do
442
+ @feed = Atom::Feed.load_feed(File.open('spec/conformance/linktests.xml'))
443
+ @entries = @feed.entries
444
+ end
445
+
446
+ describe 'linktest1' do
447
+ before(:all) do
448
+ @entry = @entries[0]
449
+ end
450
+
451
+ it "should pick single alternate link without rel" do
452
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
453
+ end
454
+ end
455
+
456
+ describe 'linktest2' do
457
+ before(:all) do
458
+ @entry = @entries[1]
459
+ end
460
+
461
+ it "should be picky about case of alternate rel" do
462
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
463
+ end
464
+
465
+ it "should be picky when picking the alternate by type" do
466
+ @entry.alternate('text/plain').href.should == 'http://www.snellspace.com/public/linktests/alternate2'
467
+ end
468
+ end
469
+
470
+ describe 'linktest3' do
471
+ before(:all) do
472
+ @entry = @entries[2]
473
+ end
474
+
475
+ it "should parse all links" do
476
+ @entry.should have(5).links
477
+ end
478
+
479
+ it "should pick the alternate from a full list of core types" do
480
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
481
+ end
482
+ end
483
+
484
+ describe 'linktest4' do
485
+ before(:all) do
486
+ @entry = @entries[3]
487
+ end
488
+
489
+ it "should parse all links" do
490
+ @entry.should have(6).links
491
+ end
492
+
493
+ it "should pick the first alternate from a full list of core types with an extra alternate" do
494
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
495
+ end
496
+
497
+ it "should pick the alternate by type from a full list of core types with an extra alternate" do
498
+ @entry.alternate('text/plain').href.should == 'http://www.snellspace.com/public/linktests/alternate2'
499
+ end
500
+ end
501
+
502
+ describe 'linktest5' do
503
+ before(:all) do
504
+ @entry = @entries[4]
505
+ end
506
+
507
+ it "should parse all links" do
508
+ @entry.should have(2).links
509
+ end
510
+
511
+ it "should pick the alternate without choking on a non-core type" do
512
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
513
+ end
514
+
515
+ it "should include the non-core type in the list of links" do
516
+ @entry.links.map(&:href).should include('http://www.snellspace.com/public/linktests/license')
517
+ end
518
+ end
519
+
520
+ describe 'linktest6' do
521
+ before(:all) do
522
+ @entry = @entries[5]
523
+ end
524
+
525
+ it "should parse all links" do
526
+ @entry.should have(2).links
527
+ end
528
+
529
+ it "should pick the alternate without choking on a non-core type identified by a uri" do
530
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
531
+ end
532
+
533
+ it "should include the non-core type in the list of links identified by a uri" do
534
+ @entry.links.map(&:href).should include('http://www.snellspace.com/public/linktests/example')
535
+ end
536
+ end
537
+
538
+ describe 'linktest7' do
539
+ before(:all) do
540
+ @entry = @entries[6]
541
+ end
542
+
543
+ it "should parse all links" do
544
+ @entry.should have(2).links
545
+ end
546
+
547
+ it "should pick the alternate without choking on a non-core type" do
548
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
549
+ end
550
+
551
+ it "should include the non-core type in the list of links" do
552
+ @entry.links.map(&:href).should include('http://www.snellspace.com/public/linktests/license')
553
+ end
554
+ end
555
+
556
+ describe 'linktest8' do
557
+ before(:all) do
558
+ @entry = @entries[7]
559
+ end
560
+
561
+ it "should parse all links" do
562
+ @entry.should have(2).links
563
+ end
564
+
565
+ it "should pick the alternate without choking on a non-core type identified by a uri" do
566
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/linktests/alternate'
567
+ end
568
+
569
+ it "should include the non-core type in the list of links identified by a uri" do
570
+ @entry.links.map(&:href).should include('http://www.snellspace.com/public/linktests/example')
571
+ end
572
+ end
573
+ end
574
+
575
+ describe 'ordertest.atom' do
576
+ before(:all) do
577
+ @feed = Atom::Feed.load_feed(File.open('spec/conformance/ordertest.xml'))
578
+ end
579
+
580
+ it 'should have 9 entries' do
581
+ @feed.should have(9).entries
582
+ end
583
+
584
+ describe 'ordertest1' do
585
+ before(:each) do
586
+ @entry = @feed.entries[0]
587
+ end
588
+
589
+ it "should have the correct title" do
590
+ @entry.title.should == 'Simple order, nothing fancy'
591
+ end
592
+ end
593
+
594
+ describe 'ordertest2' do
595
+ before(:each) do
596
+ @entry = @feed.entries[1]
597
+ end
598
+
599
+ it "should have the correct title" do
600
+ @entry.title.should == 'Same as the first, only mixed up a bit'
601
+ end
602
+ end
603
+
604
+ describe "ordertest3" do
605
+ before(:each) do
606
+ @entry = @feed.entries[2]
607
+ end
608
+
609
+ it "should have the correct title" do
610
+ @entry.title.should == 'Multiple alt link elements, which one does your reader show?'
611
+ end
612
+
613
+ it "should pick the first alternate" do
614
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/alternate'
615
+ end
616
+ end
617
+
618
+ describe 'ordertest4' do
619
+ before(:each) do
620
+ @entry = @feed.entries[3]
621
+ end
622
+
623
+ it "should have the correct title" do
624
+ @entry.title.should == 'Multiple link elements, does your feed reader show the "alternate" correctly?'
625
+ end
626
+
627
+ it "should pick the right link" do
628
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/alternate'
629
+ end
630
+ end
631
+
632
+ describe 'ordertest5' do
633
+ before(:each) do
634
+ @entry = @feed.entries[4]
635
+ end
636
+
637
+ it "should have a source" do
638
+ @entry.source.should_not be_nil
639
+ end
640
+
641
+ it "should have the correct title" do
642
+ @entry.title.should == 'Entry with a source first'
643
+ end
644
+
645
+ it "should have the correct updated" do
646
+ @entry.updated.should == Time.parse('2006-01-26T09:20:05Z')
647
+ end
648
+
649
+ it "should have the correct alt link" do
650
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/alternate'
651
+ end
652
+
653
+ describe Atom::Source do
654
+ before(:each) do
655
+ @source = @entry.source
656
+ end
657
+
658
+ it "should have an id" do
659
+ @source.id.should == 'tag:example.org,2006:atom/conformance/element_order'
660
+ end
661
+
662
+ it "should have a title" do
663
+ @source.title.should == 'Order Matters'
664
+ end
665
+
666
+ it "should have a subtitle" do
667
+ @source.subtitle.should == 'Testing how feed readers handle the order of entry elements'
668
+ end
669
+
670
+ it "should have a updated" do
671
+ @source.updated.should == Time.parse('2006-01-26T09:16:00Z')
672
+ end
673
+
674
+ it "should have an author" do
675
+ @source.should have(1).authors
676
+ end
677
+
678
+ it "should have the right name for the author" do
679
+ @source.authors.first.name.should == 'James Snell'
680
+ end
681
+
682
+ it "should have 2 links" do
683
+ @source.should have(2).links
684
+ end
685
+
686
+ it "should have an alternate" do
687
+ @source.alternate.href.should == 'http://www.snellspace.com/wp/?p=255'
688
+ end
689
+
690
+ it "should have a self" do
691
+ @source.self.href.should == 'http://www.snellspace.com/public/ordertest.xml'
692
+ end
693
+ end
694
+ end
695
+
696
+ describe 'ordertest6' do
697
+ before(:each) do
698
+ @entry = @feed.entries[5]
699
+ end
700
+
701
+ it "should have a source" do
702
+ @entry.source.should_not be_nil
703
+ end
704
+
705
+ it "should have the correct title" do
706
+ @entry.title.should == 'Entry with a source last'
707
+ end
708
+
709
+ it "should have the correct updated" do
710
+ @entry.updated.should == Time.parse('2006-01-26T09:20:06Z')
711
+ end
712
+
713
+ it "should have the correct alt link" do
714
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/alternate'
715
+ end
716
+ end
717
+
718
+ describe 'ordetest7' do
719
+ before(:each) do
720
+ @entry = @feed.entries[6]
721
+ end
722
+
723
+ it "should have a source" do
724
+ @entry.source.should_not be_nil
725
+ end
726
+
727
+ it "should have the correct title" do
728
+ @entry.title.should == 'Entry with a source in the middle'
729
+ end
730
+
731
+ it "should have the correct updated" do
732
+ @entry.updated.should == Time.parse('2006-01-26T09:20:07Z')
733
+ end
734
+
735
+ it "should have the correct alt link" do
736
+ @entry.alternate.href.should == 'http://www.snellspace.com/public/alternate'
737
+ end
738
+ end
739
+
740
+ describe 'ordertest8' do
741
+ before(:each) do
742
+ @entry = @feed.entries[7]
743
+ end
744
+
745
+ it "should have the right title" do
746
+ @entry.title.should == 'Atom elements in an extension element'
747
+ end
748
+
749
+ it "should have right id" do
750
+ @entry.id.should == 'tag:example.org,2006:atom/conformance/element_order/8'
751
+ end
752
+ end
753
+
754
+ describe 'ordertest9' do
755
+ before(:each) do
756
+ @entry = @feed.entries[8]
757
+ end
758
+
759
+ it "should have the right title" do
760
+ @entry.title.should == 'Atom elements in an extension element'
761
+ end
762
+
763
+ it 'should have the right id' do
764
+ @entry.id.should == 'tag:example.org,2006:atom/conformance/element_order/9'
765
+ end
766
+ end
767
+ end
768
+ end
769
+
770
+ describe 'pagination' do
771
+ describe 'first_paged_feed.atom' do
772
+ before(:all) do
773
+ @feed = Atom::Feed.load_feed(File.open('spec/paging/first_paged_feed.atom'))
774
+ end
775
+
776
+ it "should be first?" do
777
+ @feed.should be_first
778
+ end
779
+
780
+ it "should not be last?" do
781
+ @feed.should_not be_last
782
+ end
783
+
784
+ it "should have next" do
785
+ @feed.next_page.href.should == 'http://example.org/index.atom?page=2'
786
+ end
787
+
788
+ it "should not have prev" do
789
+ @feed.prev_page.should be_nil
790
+ end
791
+
792
+ it "should have last" do
793
+ @feed.last_page.href.should == 'http://example.org/index.atom?page=10'
794
+ end
795
+
796
+ it "should have first" do
797
+ @feed.first_page.href.should == 'http://example.org/index.atom'
798
+ end
799
+ end
800
+
801
+ describe 'middle_paged_feed.atom' do
802
+ before(:all) do
803
+ @feed = Atom::Feed.load_feed(File.open('spec/paging/middle_paged_feed.atom'))
804
+ end
805
+
806
+ it "should not be last?" do
807
+ @feed.should_not be_last
808
+ end
809
+
810
+ it "should not be first?" do
811
+ @feed.should_not be_first
812
+ end
813
+
814
+ it "should have next_page" do
815
+ @feed.next_page.href.should == 'http://example.org/index.atom?page=4'
816
+ end
817
+
818
+ it "should have prev_page" do
819
+ @feed.prev_page.href.should == 'http://example.org/index.atom?page=2'
820
+ end
821
+
822
+ it "should have last_page" do
823
+ @feed.last_page.href.should == 'http://example.org/index.atom?page=10'
824
+ end
825
+
826
+ it "should have first_page" do
827
+ @feed.first_page.href.should == 'http://example.org/index.atom'
828
+ end
829
+ end
830
+
831
+ describe 'last_paged_feed.atom' do
832
+ before(:all) do
833
+ @feed = Atom::Feed.load_feed(File.open('spec/paging/last_paged_feed.atom'))
834
+ end
835
+
836
+ it "should not be first?" do
837
+ @feed.should_not be_first
838
+ end
839
+
840
+ it "should be last?" do
841
+ @feed.should be_last
842
+ end
843
+
844
+ it "should have prev_page" do
845
+ @feed.prev_page.href.should == 'http://example.org/index.atom?page=9'
846
+ end
847
+
848
+ it "should not have next_page" do
849
+ @feed.next_page.should be_nil
850
+ end
851
+
852
+ it "should have first_page" do
853
+ @feed.first_page.href.should == 'http://example.org/index.atom'
854
+ end
855
+
856
+ it "should have last_page" do
857
+ @feed.last_page.href.should == 'http://example.org/index.atom?page=10'
858
+ end
859
+ end
860
+
861
+ describe 'pagination using each_entries' do
862
+ before(:each) do
863
+ @feed = Atom::Feed.load_feed(File.open('spec/paging/first_paged_feed.atom'))
864
+
865
+
866
+ end
867
+
868
+ it "should paginate through each entry" do
869
+ response1 = Net::HTTPSuccess.new(nil, nil, nil)
870
+ response1.stub!(:body).and_return(File.read('spec/paging/middle_paged_feed.atom'))
871
+ Net::HTTP.should_receive(:get_response).with(URI.parse('http://example.org/index.atom?page=2')).and_return(response1)
872
+
873
+ response2 = Net::HTTPSuccess.new(nil, nil, nil)
874
+ response2.stub!(:body).and_return(File.read('spec/paging/last_paged_feed.atom'))
875
+ Net::HTTP.should_receive(:get_response).with(URI.parse('http://example.org/index.atom?page=4')).and_return(response2)
876
+
877
+ entry_count = 0
878
+ @feed.each_entry(:paginate => true) do |entry|
879
+ entry_count += 1
880
+ end
881
+
882
+ entry_count.should == 3
883
+ end
884
+
885
+ it "should not paginate through each entry when paginate not true" do
886
+ entry_count = 0
887
+ @feed.each_entry do |entry|
888
+ entry_count += 1
889
+ end
890
+
891
+ entry_count.should == 1
892
+ end
893
+
894
+ it "should only paginate up to since" do
895
+ response1 = Net::HTTPSuccess.new(nil, nil, nil)
896
+ response1.stub!(:body).and_return(File.read('spec/paging/middle_paged_feed.atom'))
897
+ Net::HTTP.should_receive(:get_response).with(URI.parse('http://example.org/index.atom?page=2')).and_return(response1)
898
+ Net::HTTP.should_receive(:get_response).with(URI.parse('http://example.org/index.atom?page=4')).never
899
+
900
+ entry_count = 0
901
+ @feed.each_entry(:paginate => true, :since => Time.parse('2003-11-19T18:30:02Z')) do |entry|
902
+ entry_count += 1
903
+ end
904
+
905
+ entry_count.should == 1
906
+ end
907
+ end
908
+ end
909
+
910
+ describe Atom::Link do
911
+ before(:each) do
912
+ @href = 'http://example.org/next'
913
+ @link = Atom::Link.new(:rel => 'next', :href => @href)
914
+ end
915
+
916
+ it "should fetch feed for fetch_next" do
917
+ response = Net::HTTPSuccess.new(nil, nil, nil)
918
+ response.stub!(:body).and_return(File.read('spec/paging/middle_paged_feed.atom'))
919
+ Net::HTTP.should_receive(:get_response).with(URI.parse(@href)).and_return(response)
920
+ @link.fetch.should be_an_instance_of(Atom::Feed)
921
+ end
922
+
923
+ it "should fetch content when response is not xml" do
924
+ response = Net::HTTPSuccess.new(nil, nil, nil)
925
+ response.stub!(:body).and_return('some text.')
926
+ Net::HTTP.should_receive(:get_response).with(URI.parse(@href)).and_return(response)
927
+ @link.fetch.should == 'some text.'
928
+ end
929
+
930
+ it "should fetch content when response is not atom" do
931
+ content = <<-END
932
+ <?xml version="1.0" ?>
933
+ <foo>
934
+ <bar>text</bar>
935
+ </foo>
936
+ END
937
+ response = Net::HTTPSuccess.new(nil, nil, nil)
938
+ response.stub!(:body).and_return(content)
939
+ Net::HTTP.should_receive(:get_response).with(URI.parse(@href)).and_return(response)
940
+ @link.fetch.should == content
941
+ end
942
+ end
943
+
944
+ describe Atom::Entry do
945
+ before(:all) do
946
+ @entry = Atom::Entry.load_entry(File.read('spec/fixtures/entry.atom'))
947
+ end
948
+
949
+ it "should be == to itself" do
950
+ @entry.should == Atom::Entry.load_entry(File.read('spec/fixtures/entry.atom'))
951
+ end
952
+
953
+ it "should be != if something changes" do
954
+ @other = Atom::Entry.load_entry(File.read('spec/fixtures/entry.atom'))
955
+ @other.title = 'foo'
956
+ @entry.should_not == @other
957
+ end
958
+
959
+ it "should be != if content changes" do
960
+ @other = Atom::Entry.load_entry(File.read('spec/fixtures/entry.atom'))
961
+ @other.content.type = 'html'
962
+ @entry.should_not == @other
963
+ end
964
+
965
+ it "should output itself" do
966
+ other = Atom::Entry.load_entry(@entry.to_xml)
967
+ @entry.should == other
968
+ end
969
+
970
+ it "should properly escape titles" do
971
+ @entry.title = "Breaking&nbsp;Space"
972
+ other = Atom::Entry.load_entry(@entry.to_xml)
973
+ @entry.should == other
974
+ end
975
+ end
976
+
977
+ describe 'Atom::Feed initializer' do
978
+ it "should create an empty Feed" do
979
+ lambda { Atom::Feed.new }.should_not raise_error
980
+ end
981
+
982
+ it "should yield to a block" do
983
+ lambda do
984
+ Atom::Feed.new do |f|
985
+ f.should be_an_instance_of(Atom::Feed)
986
+ throw :yielded
987
+ end
988
+ end.should throw_symbol(:yielded)
989
+ end
990
+ end
991
+
992
+ describe 'Atom::Entry initializer' do
993
+ it "should create an empty feed" do
994
+ lambda { Atom::Entry.new }.should_not raise_error
995
+ end
996
+
997
+ it "should yield to a block" do
998
+ lambda do
999
+ Atom::Entry.new do |f|
1000
+ f.should be_an_instance_of(Atom::Entry)
1001
+ throw :yielded
1002
+ end
1003
+ end.should throw_symbol(:yielded)
1004
+ end
1005
+ end
1006
+
1007
+ describe Atom::Content::Html do
1008
+ it "should escape ampersands in entities" do
1009
+ Atom::Content::Html.new("&nbsp;").to_xml.to_s.should == "<content type=\"html\">&amp;nbsp;</content>"
1010
+ end
1011
+ end
1012
+ end