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.
- data/History.txt +7 -0
- data/License.txt +20 -0
- data/Manifest.txt +52 -0
- data/README.txt +123 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +72 -0
- data/config/requirements.rb +17 -0
- data/lib/atom.rb +566 -0
- data/lib/atom/pub.rb +185 -0
- data/lib/atom/version.rb +9 -0
- data/lib/atom/xml/parser.rb +223 -0
- data/setup.rb +1585 -0
- data/spec/app/member_entry.atom +31 -0
- data/spec/app/service.xml +36 -0
- data/spec/atom/pub_spec.rb +289 -0
- data/spec/atom_spec.rb +1012 -0
- data/spec/conformance/baseuri.atom +19 -0
- data/spec/conformance/divtest.atom +32 -0
- data/spec/conformance/linktests.xml +93 -0
- data/spec/conformance/nondefaultnamespace-baseline.atom +25 -0
- data/spec/conformance/nondefaultnamespace-xhtml.atom +25 -0
- data/spec/conformance/nondefaultnamespace.atom +25 -0
- data/spec/conformance/ordertest.xml +112 -0
- data/spec/conformance/title/html-cdata.atom +22 -0
- data/spec/conformance/title/html-entity.atom +22 -0
- data/spec/conformance/title/html-ncr.atom +22 -0
- data/spec/conformance/title/text-cdata.atom +22 -0
- data/spec/conformance/title/text-entity.atom +21 -0
- data/spec/conformance/title/text-ncr.atom +21 -0
- data/spec/conformance/title/xhtml-entity.atom +21 -0
- data/spec/conformance/title/xhtml-ncr.atom +21 -0
- data/spec/conformance/unknown-namespace.atom +25 -0
- data/spec/conformance/xmlbase.atom +133 -0
- data/spec/fixtures/complex_single_entry.atom +45 -0
- data/spec/fixtures/created_entry.atom +31 -0
- data/spec/fixtures/entry.atom +30 -0
- data/spec/fixtures/multiple_entry.atom +0 -0
- data/spec/fixtures/simple_single_entry.atom +21 -0
- data/spec/paging/first_paged_feed.atom +21 -0
- data/spec/paging/last_paged_feed.atom +21 -0
- data/spec/paging/middle_paged_feed.atom +22 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +24 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +15 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +11 -0
- data/website/index.txt +39 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.rhtml +48 -0
- 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 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(" ").to_xml.to_s.should == "<content type=\"html\">&nbsp;</content>"
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
end
|