ratom-ssl 0.0.0

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 (49) hide show
  1. data/.gitignore +4 -0
  2. data/History.txt +118 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +295 -0
  5. data/Rakefile +55 -0
  6. data/VERSION.yml +5 -0
  7. data/lib/atom/configuration.rb +24 -0
  8. data/lib/atom/pub.rb +253 -0
  9. data/lib/atom/version.rb +7 -0
  10. data/lib/atom/xml/parser.rb +376 -0
  11. data/lib/atom.rb +771 -0
  12. data/ratom-ssl.gemspec +98 -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 +504 -0
  16. data/spec/atom_spec.rb +1336 -0
  17. data/spec/conformance/baseuri.atom +19 -0
  18. data/spec/conformance/divtest.atom +32 -0
  19. data/spec/conformance/linktests.xml +103 -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/entry_with_custom_extensions.atom +7 -0
  38. data/spec/fixtures/entry_with_simple_extensions.atom +30 -0
  39. data/spec/fixtures/entry_with_single_custom_extension.atom +6 -0
  40. data/spec/fixtures/multiple_entry.atom +0 -0
  41. data/spec/fixtures/simple_single_entry.atom +21 -0
  42. data/spec/fixtures/with_stylesheet.atom +8 -0
  43. data/spec/paging/first_paged_feed.atom +21 -0
  44. data/spec/paging/last_paged_feed.atom +21 -0
  45. data/spec/paging/middle_paged_feed.atom +22 -0
  46. data/spec/property.rb +31 -0
  47. data/spec/spec.opts +1 -0
  48. data/spec/spec_helper.rb +43 -0
  49. metadata +140 -0
data/ratom-ssl.gemspec ADDED
@@ -0,0 +1,98 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ratom-ssl}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Peerworks", "Sean Geoghegan", "Kenton White"]
12
+ s.date = %q{2010-04-19}
13
+ s.description = %q{A fast Atom Syndication and Publication API based on libxml}
14
+ s.email = %q{jkentonwhite@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "History.txt",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION.yml",
26
+ "lib/atom.rb",
27
+ "lib/atom/configuration.rb",
28
+ "lib/atom/pub.rb",
29
+ "lib/atom/version.rb",
30
+ "lib/atom/xml/parser.rb",
31
+ "ratom-ssl.gemspec",
32
+ "spec/app/member_entry.atom",
33
+ "spec/app/service.xml",
34
+ "spec/atom/pub_spec.rb",
35
+ "spec/atom_spec.rb",
36
+ "spec/conformance/baseuri.atom",
37
+ "spec/conformance/divtest.atom",
38
+ "spec/conformance/linktests.xml",
39
+ "spec/conformance/nondefaultnamespace-baseline.atom",
40
+ "spec/conformance/nondefaultnamespace-xhtml.atom",
41
+ "spec/conformance/nondefaultnamespace.atom",
42
+ "spec/conformance/ordertest.xml",
43
+ "spec/conformance/title/html-cdata.atom",
44
+ "spec/conformance/title/html-entity.atom",
45
+ "spec/conformance/title/html-ncr.atom",
46
+ "spec/conformance/title/text-cdata.atom",
47
+ "spec/conformance/title/text-entity.atom",
48
+ "spec/conformance/title/text-ncr.atom",
49
+ "spec/conformance/title/xhtml-entity.atom",
50
+ "spec/conformance/title/xhtml-ncr.atom",
51
+ "spec/conformance/unknown-namespace.atom",
52
+ "spec/conformance/xmlbase.atom",
53
+ "spec/fixtures/complex_single_entry.atom",
54
+ "spec/fixtures/created_entry.atom",
55
+ "spec/fixtures/entry.atom",
56
+ "spec/fixtures/entry_with_custom_extensions.atom",
57
+ "spec/fixtures/entry_with_simple_extensions.atom",
58
+ "spec/fixtures/entry_with_single_custom_extension.atom",
59
+ "spec/fixtures/multiple_entry.atom",
60
+ "spec/fixtures/simple_single_entry.atom",
61
+ "spec/fixtures/with_stylesheet.atom",
62
+ "spec/paging/first_paged_feed.atom",
63
+ "spec/paging/last_paged_feed.atom",
64
+ "spec/paging/middle_paged_feed.atom",
65
+ "spec/property.rb",
66
+ "spec/spec.opts",
67
+ "spec/spec_helper.rb"
68
+ ]
69
+ s.homepage = %q{http://github.com/KentonWhite/ratom-ssl}
70
+ s.rdoc_options = ["--charset=UTF-8"]
71
+ s.require_paths = ["lib"]
72
+ s.rubyforge_project = %q{ratom}
73
+ s.rubygems_version = %q{1.3.6}
74
+ s.summary = %q{Atom Syndication and Publication API with SSL}
75
+ s.test_files = [
76
+ "spec/atom/pub_spec.rb",
77
+ "spec/atom_spec.rb",
78
+ "spec/property.rb",
79
+ "spec/spec_helper.rb"
80
+ ]
81
+
82
+ if s.respond_to? :specification_version then
83
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
84
+ s.specification_version = 3
85
+
86
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
87
+ s.add_development_dependency(%q<rspec>, [">= 0"])
88
+ s.add_runtime_dependency(%q<libxml-ruby>, [">= 1.1.2"])
89
+ else
90
+ s.add_dependency(%q<rspec>, [">= 0"])
91
+ s.add_dependency(%q<libxml-ruby>, [">= 1.1.2"])
92
+ end
93
+ else
94
+ s.add_dependency(%q<rspec>, [">= 0"])
95
+ s.add_dependency(%q<libxml-ruby>, [">= 1.1.2"])
96
+ end
97
+ end
98
+
@@ -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,504 @@
1
+ # Copyright (c) 2008 The Kaphan Foundation
2
+ #
3
+ # For licensing information see LICENSE.
4
+ #
5
+ # Please visit http://www.peerworks.org/contact 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
+ shared_examples_for 'parser of spec/app/service.xml' do
16
+ it "should have 2 workspaces" do
17
+ @service.should have(2).workspaces
18
+ end
19
+
20
+ it "should have a title" do
21
+ @workspace.title.should == "Main Site"
22
+ end
23
+
24
+ it "should have 2 collections" do
25
+ @workspace.should have(2).collections
26
+ end
27
+
28
+ it "should have the right href" do
29
+ @collection1.href.should == 'http://example.org/blog/main'
30
+ end
31
+
32
+ it "should have categories" do
33
+ @collection1.categories.should_not be_nil
34
+ end
35
+
36
+ it "should have a href on categories" do
37
+ @collection1.categories.href.should == "http://example.com/cats/forMain.cats"
38
+ @collection1.categories.fixed?.should be_false
39
+ end
40
+
41
+ it "should have a title" do
42
+ @collection1.title.should == 'My Blog Entries'
43
+ end
44
+
45
+ it "should have a title" do
46
+ @collection2.title.should == 'Pictures'
47
+ end
48
+
49
+ it "should have the right href" do
50
+ @collection2.href.should == 'http://example.org/blog/pic'
51
+ end
52
+
53
+ it "should not have categories" do
54
+ @collection2.categories.should be_nil
55
+ end
56
+
57
+ it "should have 3 accepts" do
58
+ @collection2.should have(3).accepts
59
+ end
60
+
61
+ it "should accept 'image/png'" do
62
+ @collection2.accepts.should include('image/png')
63
+ end
64
+
65
+ it "should accept 'image/jpeg'" do
66
+ @collection2.accepts.should include('image/jpeg')
67
+ end
68
+
69
+ it "should accept 'image/gif'" do
70
+ @collection2.accepts.should include('image/gif')
71
+ end
72
+
73
+ it "should have a title on workspace 2" do
74
+ @workspace2.title.should == 'Sidebar Blog'
75
+ end
76
+
77
+ it "should have 1 collection on workspace 2" do
78
+ @workspace2.should have(1).collections
79
+ end
80
+
81
+ it "should have a title on collection 3" do
82
+ @collection3.title.should == 'Remaindered Links'
83
+ end
84
+
85
+ it "should have 1 accept on collection 3" do
86
+ @collection3.should have(1).accepts
87
+ end
88
+
89
+ it "should accept 'application/atom+xml;type=entry'" do
90
+ @collection3.accepts.should include('application/atom+xml;type=entry')
91
+ end
92
+
93
+ it "should have categories" do
94
+ @collection3.categories.should_not be_nil
95
+ end
96
+
97
+ it "should have fixed == 'yes' on categories" do
98
+ @collection3.categories.fixed.should == "yes"
99
+ end
100
+
101
+ it "should have fixed? == true on categories" do
102
+ @collection3.categories.fixed?.should be_true
103
+ end
104
+ end
105
+
106
+ describe Atom::Pub do
107
+ describe Atom::Pub::Service do
108
+ it "should load from a URL" do
109
+ uri = URI.parse('http://example.com/service.xml')
110
+ response = Net::HTTPSuccess.new(nil, nil, nil)
111
+ response.stub!(:body).and_return(File.read('spec/app/service.xml'))
112
+ mock_http_get(uri, response)
113
+
114
+ Atom::Pub::Service.load_service(uri).should be_an_instance_of(Atom::Pub::Service)
115
+ end
116
+
117
+ it "should raise ArgumentError with a non-http URL" do
118
+ lambda { Atom::Pub::Service.load_service(URI.parse('file:/tmp')) }.should raise_error(ArgumentError)
119
+ end
120
+
121
+ it "should be able to be created without xml" do
122
+ lambda { Atom::Pub::Service.new }.should_not raise_error
123
+ end
124
+
125
+ it "should yield in the initializer" do
126
+ yielded = false
127
+ Atom::Pub::Service.new do
128
+ yielded = true
129
+ end
130
+
131
+ yielded.should be_true
132
+ end
133
+
134
+ it "should parse it's output" do
135
+ orig = File.read('spec/app/service.xml')
136
+ svc = Atom::Pub::Service.load_service(orig)
137
+ xml = svc.to_xml
138
+ lambda do
139
+ Atom::Pub::Service.load_service(xml)
140
+ end.should_not raise_error
141
+ end
142
+
143
+ describe "load_service" do
144
+ before(:all) do
145
+ @service = Atom::Pub::Service.load_service(File.open('spec/app/service.xml'))
146
+ @workspace = @service.workspaces.first
147
+ @workspace2 = @service.workspaces[1]
148
+ @collection1 = @workspace.collections.first
149
+ @collection2 = @workspace.collections[1]
150
+ @collection3 = @workspace2.collections.first
151
+ end
152
+
153
+ it_should_behave_like 'parser of spec/app/service.xml'
154
+ end
155
+
156
+ describe "load_service with authentication" do
157
+ it "should pass credentials to the server" do
158
+ uri = URI.parse('http://example.com/service.xml')
159
+ response = Net::HTTPSuccess.new(nil, nil, nil)
160
+ response.stub!(:body).and_return(File.read('spec/app/service.xml'))
161
+ mock_http_get(uri, response, 'user', 'pass')
162
+ Atom::Pub::Service.load_service(uri, :user => 'user', :pass => 'pass')
163
+ end
164
+
165
+ it "should pass credentials on to the collections" do
166
+ uri = URI.parse('http://example.com/service.xml')
167
+ response = Net::HTTPSuccess.new(nil, nil, nil)
168
+ response.stub!(:body).and_return(File.read('spec/app/service.xml'))
169
+ mock_http_get(uri, response, 'user', 'pass')
170
+ pub = Atom::Pub::Service.load_service(uri, :user => 'user', :pass => 'pass')
171
+
172
+ uri2 = URI.parse('http://example.org/blog/main')
173
+ response2 = Net::HTTPSuccess.new(nil, nil, nil)
174
+ response2.stub!(:body).and_return(File.read('spec/fixtures/simple_single_entry.atom'))
175
+ mock_http_get(uri2, response2, 'user', 'pass')
176
+ pub.workspaces.first.collections.first.feed(:user => 'user', :pass => 'pass')
177
+ end
178
+ end
179
+
180
+ describe "#to_xml" do
181
+ before(:each) do
182
+ @svc = Atom::Pub::Service.load_service(File.read('spec/app/service.xml'))
183
+ @xml = @svc.to_xml
184
+ @service = Atom::Pub::Service.load_service(@xml)
185
+ @workspace = @service.workspaces.first
186
+ @workspace2 = @service.workspaces[1]
187
+ @collection1 = @workspace.collections.first
188
+ @collection2 = @workspace.collections[1]
189
+ @collection3 = @workspace2.collections.first
190
+ end
191
+
192
+ it "should put title in Atom namespace" do
193
+ @xml.should match(%r{atom:title})
194
+ end
195
+
196
+ it_should_behave_like 'parser of spec/app/service.xml'
197
+ end
198
+ end
199
+
200
+ describe Atom::Pub::Collection do
201
+ describe '.new' do
202
+ it "should set the href from the hash" do
203
+ collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
204
+ collection.href.should == 'http://example.org/blog'
205
+ end
206
+
207
+ it "should set the href from a block" do
208
+ collection = Atom::Pub::Collection.new do |c|
209
+ c.href = "http://example.org/blog"
210
+ end
211
+ collection.href.should == 'http://example.org/blog'
212
+ end
213
+ end
214
+
215
+ it "should return the feed" do
216
+ collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
217
+ response = Net::HTTPSuccess.new(nil, nil, nil)
218
+ response.stub!(:body).and_return(File.read('spec/fixtures/simple_single_entry.atom'))
219
+ mock_http_get(URI.parse(collection.href), response)
220
+ collection.feed.should be_an_instance_of(Atom::Feed)
221
+ end
222
+
223
+ describe '#publish' do
224
+ before(:each) do
225
+ @collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
226
+ @request_headers = {'Accept' => 'application/atom+xml',
227
+ 'Content-Type' => 'application/atom+xml;type=entry',
228
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
229
+ }
230
+ end
231
+
232
+ it "should send a POST request when an entry is published" do
233
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
234
+
235
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
236
+
237
+ request = mock('request')
238
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
239
+
240
+ http = mock('http')
241
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
242
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
243
+
244
+ created = @collection.publish(entry)
245
+ created.should == entry
246
+ end
247
+
248
+ it "should send a POST with basic auth request when an entry is published" do
249
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
250
+
251
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
252
+
253
+ request = mock('request')
254
+ request.should_receive(:basic_auth).with('user', 'pass')
255
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
256
+
257
+ http = mock('http')
258
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
259
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
260
+
261
+ created = @collection.publish(entry, :user => 'user', :pass => 'pass')
262
+ created.should == entry
263
+ end
264
+
265
+ if Atom::Configuration.auth_hmac_enabled?
266
+ it "should send a POST with hmac authentication when an entry is published" do
267
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
268
+
269
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
270
+
271
+ http = mock('http')
272
+ http.should_receive(:request) do |request, entry_xml|
273
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*/)
274
+ response
275
+ end
276
+
277
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
278
+
279
+ created = @collection.publish(entry, :hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
280
+ created.should == entry
281
+ end
282
+ else
283
+ xit "should send a POST with hmac authentication when an entry is published"
284
+ end
285
+
286
+ it "should behave well when no content is returned" do
287
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
288
+
289
+ response = mock_response(Net::HTTPCreated, " ")
290
+
291
+ request = mock('request')
292
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
293
+
294
+ http = mock('http')
295
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
296
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
297
+
298
+ created = @collection.publish(entry)
299
+ created.should == entry
300
+ end
301
+
302
+ it "should raise error when response is not HTTPCreated" do
303
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
304
+ response = mock_response(Net::HTTPPreconditionFailed, "")
305
+
306
+ request = mock('request')
307
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
308
+
309
+ http = mock('http')
310
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
311
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
312
+
313
+ lambda { @collection.publish(entry) }.should raise_error(Atom::Pub::ProtocolError)
314
+ end
315
+
316
+ it "should copy Location into edit link of entry" do
317
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
318
+
319
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s, 'Location' => 'http://example.org/edit/entry1.atom')
320
+
321
+ request = mock('request')
322
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
323
+
324
+ http = mock('http')
325
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
326
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
327
+
328
+ created = @collection.publish(entry)
329
+ created.edit_link.should_not be_nil
330
+ created.edit_link.href.should == 'http://example.org/edit/entry1.atom'
331
+ end
332
+
333
+ it "should update the entry when response is different" do
334
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
335
+ response = mock_response(Net::HTTPCreated, File.read('spec/fixtures/created_entry.atom'),
336
+ 'Location' => 'http://example.org/edit/atom')
337
+
338
+ request = mock('request')
339
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
340
+
341
+ http = mock('http')
342
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
343
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
344
+
345
+ created = @collection.publish(entry)
346
+ created.should == Atom::Entry.load_entry(File.open('spec/fixtures/created_entry.atom'))
347
+ end
348
+ end
349
+ end
350
+
351
+ describe Atom::Pub::Workspace do
352
+ it "should do the block initialization thing" do
353
+ workspace = Atom::Pub::Workspace.new do |w|
354
+ w.title = "Title"
355
+ end
356
+
357
+ workspace.title.should == "Title"
358
+ end
359
+
360
+ it "should do the hash initialization thing" do
361
+ workspace = Atom::Pub::Workspace.new(:title => 'Title')
362
+ workspace.title.should == "Title"
363
+ end
364
+ end
365
+
366
+ describe Atom::Entry do
367
+ before(:each) do
368
+ @request_headers = {'Accept' => 'application/atom+xml',
369
+ 'Content-Type' => 'application/atom+xml;type=entry',
370
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
371
+ }
372
+ end
373
+
374
+ it "should send a PUT to the edit link on save!" do
375
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
376
+ response = mock_response(Net::HTTPSuccess, nil)
377
+
378
+ request = mock('request')
379
+ Net::HTTP::Put.should_receive(:new).with('/member_entry.atom', @request_headers).and_return(request)
380
+
381
+ http = mock('http')
382
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
383
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
384
+
385
+ entry.save!
386
+ end
387
+
388
+ it "should send a PUT with auth to the edit link on save!" do
389
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
390
+ response = mock_response(Net::HTTPSuccess, nil)
391
+
392
+ request = mock('request')
393
+ request.should_receive(:basic_auth).with('user', 'pass')
394
+ Net::HTTP::Put.should_receive(:new).with('/member_entry.atom', @request_headers).and_return(request)
395
+
396
+ http = mock('http')
397
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
398
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
399
+
400
+ entry.save!(:user => 'user', :pass => 'pass')
401
+ end
402
+
403
+ if Atom::Configuration.auth_hmac_enabled?
404
+ it "should send a PUT with hmac auth to the edit link on save!" do
405
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
406
+ response = mock_response(Net::HTTPSuccess, nil)
407
+
408
+ http = mock('http')
409
+ http.should_receive(:request) do |request, entry_xml|
410
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*$/)
411
+ response
412
+ end
413
+
414
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
415
+
416
+ entry.save!(:hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
417
+ end
418
+ end
419
+
420
+ it "should send a DELETE to the edit link on delete!" do
421
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
422
+ response = mock_response(Net::HTTPSuccess, nil)
423
+
424
+ request = mock('request')
425
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
426
+
427
+ http = mock('http')
428
+ http.should_receive(:request).with(request).and_return(response)
429
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
430
+
431
+ entry.destroy!
432
+ end
433
+
434
+ it "should send a DELETE with basic auth to the edit link on delete!" do
435
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
436
+ response = mock_response(Net::HTTPSuccess, nil)
437
+
438
+ request = mock('request')
439
+ request.should_receive(:basic_auth).with('user', 'pass')
440
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
441
+
442
+ http = mock('http')
443
+ http.should_receive(:request).with(request).and_return(response)
444
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
445
+
446
+ entry.destroy!(:user => 'user', :pass => 'pass')
447
+ end
448
+
449
+ if Atom::Configuration.auth_hmac_enabled?
450
+ it "should send a DELETE with hmac auth to the edit link on delete!" do
451
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
452
+ response = mock_response(Net::HTTPSuccess, nil)
453
+
454
+ http = mock('http')
455
+ http.should_receive(:request) do |request|
456
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*$/)
457
+ response
458
+ end
459
+
460
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
461
+
462
+ entry.destroy!(:hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
463
+ end
464
+ end
465
+
466
+ it "should raise exception on save! without an edit link" do
467
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
468
+ lambda { entry.save! }.should raise_error(Atom::Pub::NotSupported)
469
+ end
470
+
471
+ it "should raise exception on save failure" do
472
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
473
+ response = mock_response(Net::HTTPClientError, nil)
474
+
475
+ request = mock('request')
476
+ Net::HTTP::Put.should_receive(:new).with('/member_entry.atom', @request_headers).and_return(request)
477
+
478
+ http = mock('http')
479
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
480
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
481
+
482
+ lambda { entry.save! }.should raise_error(Atom::Pub::ProtocolError)
483
+ end
484
+
485
+ it "should raise exception on destroy! without an edit link" do
486
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
487
+ lambda { entry.destroy! }.should raise_error(Atom::Pub::NotSupported)
488
+ end
489
+
490
+ it "should raise exception on destroy failure" do
491
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
492
+ response = mock_response(Net::HTTPClientError, nil)
493
+
494
+ request = mock('request')
495
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
496
+
497
+ http = mock('http')
498
+ http.should_receive(:request).with(request).and_return(response)
499
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
500
+
501
+ lambda { entry.destroy! }.should raise_error(Atom::Pub::ProtocolError)
502
+ end
503
+ end
504
+ end