ratom-instructure 0.6.9

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/History.txt +135 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +293 -0
  4. data/Rakefile +59 -0
  5. data/VERSION.yml +5 -0
  6. data/lib/atom.rb +796 -0
  7. data/lib/atom/configuration.rb +24 -0
  8. data/lib/atom/pub.rb +251 -0
  9. data/lib/atom/version.rb +7 -0
  10. data/lib/atom/xml/parser.rb +413 -0
  11. data/ratom.gemspec +95 -0
  12. data/spec/app/member_entry.atom +31 -0
  13. data/spec/app/service.xml +36 -0
  14. data/spec/app/service_xml_base.xml +37 -0
  15. data/spec/atom/pub_spec.rb +517 -0
  16. data/spec/atom_spec.rb +1385 -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 +8 -0
  38. data/spec/fixtures/entry_with_simple_extensions.atom +31 -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 +46 -0
  49. metadata +147 -0
@@ -0,0 +1,95 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ratom-instructure}
8
+ s.version = "0.6.9"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Peerworks", "Sean Geoghegan", "Jacob Fugal"]
12
+ s.date = %q{2011-07-13}
13
+ s.description = %q{A fast Atom Syndication and Publication API based on libxml}
14
+ s.email = %q{seangeo@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ "History.txt",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION.yml",
25
+ "lib/atom.rb",
26
+ "lib/atom/configuration.rb",
27
+ "lib/atom/pub.rb",
28
+ "lib/atom/version.rb",
29
+ "lib/atom/xml/parser.rb",
30
+ "ratom.gemspec",
31
+ "spec/app/member_entry.atom",
32
+ "spec/app/service.xml",
33
+ "spec/app/service_xml_base.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/lukfugl/ratom}
70
+ s.require_paths = ["lib"]
71
+ s.rubygems_version = %q{1.6.2}
72
+ s.summary = %q{Atom Syndication and Publication API}
73
+ s.test_files = [
74
+ "spec/atom/pub_spec.rb",
75
+ "spec/atom_spec.rb",
76
+ "spec/property.rb",
77
+ "spec/spec_helper.rb"
78
+ ]
79
+
80
+ if s.respond_to? :specification_version then
81
+ s.specification_version = 3
82
+
83
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
84
+ s.add_development_dependency(%q<rspec>, [">= 0"])
85
+ s.add_runtime_dependency(%q<libxml-ruby>, [">= 1.1.2"])
86
+ else
87
+ s.add_dependency(%q<rspec>, [">= 0"])
88
+ s.add_dependency(%q<libxml-ruby>, [">= 1.1.2"])
89
+ end
90
+ else
91
+ s.add_dependency(%q<rspec>, [">= 0"])
92
+ s.add_dependency(%q<libxml-ruby>, [">= 1.1.2"])
93
+ end
94
+ end
95
+
@@ -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.org/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,37 @@
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
+ xml:base="http://example.org/">
5
+ <workspace>
6
+ <atom:title>Main Site</atom:title>
7
+ <collection
8
+ href="/blog/main" >
9
+ <atom:title>My Blog Entries</atom:title>
10
+ <categories
11
+ href="/cats/forMain.cats" />
12
+ </collection>
13
+ <collection
14
+ href="http://example.org/blog/pic" >
15
+ <atom:title>Pictures</atom:title>
16
+ <accept>image/png</accept>
17
+ <accept>image/jpeg</accept>
18
+ <accept>image/gif</accept>
19
+ </collection>
20
+ </workspace>
21
+ <workspace>
22
+ <atom:title>Sidebar Blog</atom:title>
23
+ <collection
24
+ href="http://example.org/sidebar/list" >
25
+ <atom:title>Remaindered Links</atom:title>
26
+ <accept>application/atom+xml;type=entry</accept>
27
+ <categories fixed="yes">
28
+ <atom:category
29
+ scheme="http://example.org/extra-cats/"
30
+ term="joke" />
31
+ <atom:category
32
+ scheme="http://example.org/extra-cats/"
33
+ term="serious" />
34
+ </categories>
35
+ </collection>
36
+ </workspace>
37
+ </service>
@@ -0,0 +1,517 @@
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.org/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 xml:base" do
157
+ before(:all) do
158
+ @service = Atom::Pub::Service.load_service(File.open('spec/app/service_xml_base.xml'))
159
+ @workspace = @service.workspaces.first
160
+ @workspace2 = @service.workspaces[1]
161
+ @collection1 = @workspace.collections.first
162
+ @collection2 = @workspace.collections[1]
163
+ @collection3 = @workspace2.collections.first
164
+ end
165
+
166
+ it_should_behave_like 'parser of spec/app/service.xml'
167
+ end
168
+
169
+ describe "load_service with authentication" do
170
+ it "should pass credentials to the server" do
171
+ uri = URI.parse('http://example.com/service.xml')
172
+ response = Net::HTTPSuccess.new(nil, nil, nil)
173
+ response.stub!(:body).and_return(File.read('spec/app/service.xml'))
174
+ mock_http_get(uri, response, 'user', 'pass')
175
+ Atom::Pub::Service.load_service(uri, :user => 'user', :pass => 'pass')
176
+ end
177
+
178
+ it "should pass credentials on to the collections" do
179
+ uri = URI.parse('http://example.com/service.xml')
180
+ response = Net::HTTPSuccess.new(nil, nil, nil)
181
+ response.stub!(:body).and_return(File.read('spec/app/service.xml'))
182
+ mock_http_get(uri, response, 'user', 'pass')
183
+ pub = Atom::Pub::Service.load_service(uri, :user => 'user', :pass => 'pass')
184
+
185
+ uri2 = URI.parse('http://example.org/blog/main')
186
+ response2 = Net::HTTPSuccess.new(nil, nil, nil)
187
+ response2.stub!(:body).and_return(File.read('spec/fixtures/simple_single_entry.atom'))
188
+ mock_http_get(uri2, response2, 'user', 'pass')
189
+ pub.workspaces.first.collections.first.feed(:user => 'user', :pass => 'pass')
190
+ end
191
+ end
192
+
193
+ describe "#to_xml" do
194
+ before(:each) do
195
+ @svc = Atom::Pub::Service.load_service(File.read('spec/app/service.xml'))
196
+ @xml = @svc.to_xml
197
+ @service = Atom::Pub::Service.load_service(@xml)
198
+ @workspace = @service.workspaces.first
199
+ @workspace2 = @service.workspaces[1]
200
+ @collection1 = @workspace.collections.first
201
+ @collection2 = @workspace.collections[1]
202
+ @collection3 = @workspace2.collections.first
203
+ end
204
+
205
+ it "should put title in Atom namespace" do
206
+ @xml.should match(%r{atom:title})
207
+ end
208
+
209
+ it_should_behave_like 'parser of spec/app/service.xml'
210
+ end
211
+ end
212
+
213
+ describe Atom::Pub::Collection do
214
+ describe '.new' do
215
+ it "should set the href from the hash" do
216
+ collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
217
+ collection.href.should == 'http://example.org/blog'
218
+ end
219
+
220
+ it "should set the href from a block" do
221
+ collection = Atom::Pub::Collection.new do |c|
222
+ c.href = "http://example.org/blog"
223
+ end
224
+ collection.href.should == 'http://example.org/blog'
225
+ end
226
+ end
227
+
228
+ it "should return the feed" do
229
+ collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
230
+ response = Net::HTTPSuccess.new(nil, nil, nil)
231
+ response.stub!(:body).and_return(File.read('spec/fixtures/simple_single_entry.atom'))
232
+ mock_http_get(URI.parse(collection.href), response)
233
+ collection.feed.should be_an_instance_of(Atom::Feed)
234
+ end
235
+
236
+ describe '#publish' do
237
+ before(:each) do
238
+ @collection = Atom::Pub::Collection.new(:href => 'http://example.org/blog')
239
+ @request_headers = {'Accept' => 'application/atom+xml',
240
+ 'Content-Type' => 'application/atom+xml;type=entry',
241
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
242
+ }
243
+ end
244
+
245
+ it "should send a POST request when an entry is published" do
246
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
247
+
248
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
249
+
250
+ request = mock('request')
251
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
252
+
253
+ http = mock('http')
254
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
255
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
256
+
257
+ created = @collection.publish(entry)
258
+ created.should == entry
259
+ end
260
+
261
+ it "should send a POST with basic auth request when an entry is published" do
262
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
263
+
264
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
265
+
266
+ request = mock('request')
267
+ request.should_receive(:basic_auth).with('user', 'pass')
268
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
269
+
270
+ http = mock('http')
271
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
272
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
273
+
274
+ created = @collection.publish(entry, :user => 'user', :pass => 'pass')
275
+ created.should == entry
276
+ end
277
+
278
+ if Atom::Configuration.auth_hmac_enabled?
279
+ it "should send a POST with hmac authentication when an entry is published" do
280
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
281
+
282
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s)
283
+
284
+ http = mock('http')
285
+ http.should_receive(:request) do |request, entry_xml|
286
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*/)
287
+ response
288
+ end
289
+
290
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
291
+
292
+ created = @collection.publish(entry, :hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
293
+ created.should == entry
294
+ end
295
+ else
296
+ xit "should send a POST with hmac authentication when an entry is published"
297
+ end
298
+
299
+ it "should behave well when no content is returned" do
300
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
301
+
302
+ response = mock_response(Net::HTTPCreated, " ")
303
+
304
+ request = mock('request')
305
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
306
+
307
+ http = mock('http')
308
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
309
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
310
+
311
+ created = @collection.publish(entry)
312
+ created.should == entry
313
+ end
314
+
315
+ it "should raise error when response is not HTTPCreated" do
316
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
317
+ response = mock_response(Net::HTTPPreconditionFailed, "")
318
+
319
+ request = mock('request')
320
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
321
+
322
+ http = mock('http')
323
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
324
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
325
+
326
+ lambda { @collection.publish(entry) }.should raise_error(Atom::Pub::ProtocolError)
327
+ end
328
+
329
+ it "should copy Location into edit link of entry" do
330
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
331
+
332
+ response = mock_response(Net::HTTPCreated, entry.to_xml.to_s, 'Location' => 'http://example.org/edit/entry1.atom')
333
+
334
+ request = mock('request')
335
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
336
+
337
+ http = mock('http')
338
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
339
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
340
+
341
+ created = @collection.publish(entry)
342
+ created.edit_link.should_not be_nil
343
+ created.edit_link.href.should == 'http://example.org/edit/entry1.atom'
344
+ end
345
+
346
+ it "should update the entry when response is different" do
347
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
348
+ response = mock_response(Net::HTTPCreated, File.read('spec/fixtures/created_entry.atom'),
349
+ 'Location' => 'http://example.org/edit/atom')
350
+
351
+ request = mock('request')
352
+ Net::HTTP::Post.should_receive(:new).with('/blog', @request_headers).and_return(request)
353
+
354
+ http = mock('http')
355
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
356
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
357
+
358
+ created = @collection.publish(entry)
359
+ created.should == Atom::Entry.load_entry(File.open('spec/fixtures/created_entry.atom'))
360
+ end
361
+ end
362
+ end
363
+
364
+ describe Atom::Pub::Workspace do
365
+ it "should do the block initialization thing" do
366
+ workspace = Atom::Pub::Workspace.new do |w|
367
+ w.title = "Title"
368
+ end
369
+
370
+ workspace.title.should == "Title"
371
+ end
372
+
373
+ it "should do the hash initialization thing" do
374
+ workspace = Atom::Pub::Workspace.new(:title => 'Title')
375
+ workspace.title.should == "Title"
376
+ end
377
+ end
378
+
379
+ describe Atom::Entry do
380
+ before(:each) do
381
+ @request_headers = {'Accept' => 'application/atom+xml',
382
+ 'Content-Type' => 'application/atom+xml;type=entry',
383
+ 'User-Agent' => "rAtom #{Atom::VERSION::STRING}"
384
+ }
385
+ end
386
+
387
+ it "should send a PUT to the edit link on save!" do
388
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
389
+ response = mock_response(Net::HTTPSuccess, nil)
390
+
391
+ request = mock('request')
392
+ Net::HTTP::Put.should_receive(:new).with('/member_entry.atom', @request_headers).and_return(request)
393
+
394
+ http = mock('http')
395
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
396
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
397
+
398
+ entry.save!
399
+ end
400
+
401
+ it "should send a PUT with auth to the edit link on save!" do
402
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
403
+ response = mock_response(Net::HTTPSuccess, nil)
404
+
405
+ request = mock('request')
406
+ request.should_receive(:basic_auth).with('user', 'pass')
407
+ Net::HTTP::Put.should_receive(:new).with('/member_entry.atom', @request_headers).and_return(request)
408
+
409
+ http = mock('http')
410
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
411
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
412
+
413
+ entry.save!(:user => 'user', :pass => 'pass')
414
+ end
415
+
416
+ if Atom::Configuration.auth_hmac_enabled?
417
+ it "should send a PUT with hmac auth to the edit link on save!" do
418
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
419
+ response = mock_response(Net::HTTPSuccess, nil)
420
+
421
+ http = mock('http')
422
+ http.should_receive(:request) do |request, entry_xml|
423
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*$/)
424
+ response
425
+ end
426
+
427
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
428
+
429
+ entry.save!(:hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
430
+ end
431
+ end
432
+
433
+ it "should send a DELETE to the edit link on delete!" do
434
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
435
+ response = mock_response(Net::HTTPSuccess, nil)
436
+
437
+ request = mock('request')
438
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
439
+
440
+ http = mock('http')
441
+ http.should_receive(:request).with(request).and_return(response)
442
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
443
+
444
+ entry.destroy!
445
+ end
446
+
447
+ it "should send a DELETE with basic auth to the edit link on delete!" do
448
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
449
+ response = mock_response(Net::HTTPSuccess, nil)
450
+
451
+ request = mock('request')
452
+ request.should_receive(:basic_auth).with('user', 'pass')
453
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
454
+
455
+ http = mock('http')
456
+ http.should_receive(:request).with(request).and_return(response)
457
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
458
+
459
+ entry.destroy!(:user => 'user', :pass => 'pass')
460
+ end
461
+
462
+ if Atom::Configuration.auth_hmac_enabled?
463
+ it "should send a DELETE with hmac auth to the edit link on delete!" do
464
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
465
+ response = mock_response(Net::HTTPSuccess, nil)
466
+
467
+ http = mock('http')
468
+ http.should_receive(:request) do |request|
469
+ request['Authorization'].should match(/^AuthHMAC access_id:[a-zA-Z0-9\/+]+=*$/)
470
+ response
471
+ end
472
+
473
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
474
+
475
+ entry.destroy!(:hmac_access_id => 'access_id', :hmac_secret_key => 'secret')
476
+ end
477
+ end
478
+
479
+ it "should raise exception on save! without an edit link" do
480
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
481
+ lambda { entry.save! }.should raise_error(Atom::Pub::NotSupported)
482
+ end
483
+
484
+ it "should raise exception on save failure" do
485
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
486
+ response = mock_response(Net::HTTPClientError, nil)
487
+
488
+ request = mock('request')
489
+ Net::HTTP::Put.should_receive(:new).with('/member_entry.atom', @request_headers).and_return(request)
490
+
491
+ http = mock('http')
492
+ http.should_receive(:request).with(request, entry.to_xml.to_s).and_return(response)
493
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
494
+
495
+ lambda { entry.save! }.should raise_error(Atom::Pub::ProtocolError)
496
+ end
497
+
498
+ it "should raise exception on destroy! without an edit link" do
499
+ entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry.atom'))
500
+ lambda { entry.destroy! }.should raise_error(Atom::Pub::NotSupported)
501
+ end
502
+
503
+ it "should raise exception on destroy failure" do
504
+ entry = Atom::Entry.load_entry(File.open('spec/app/member_entry.atom'))
505
+ response = mock_response(Net::HTTPClientError, nil)
506
+
507
+ request = mock('request')
508
+ Net::HTTP::Delete.should_receive(:new).with('/member_entry.atom', an_instance_of(Hash)).and_return(request)
509
+
510
+ http = mock('http')
511
+ http.should_receive(:request).with(request).and_return(response)
512
+ Net::HTTP.should_receive(:start).with('example.org', 80).and_yield(http)
513
+
514
+ lambda { entry.destroy! }.should raise_error(Atom::Pub::ProtocolError)
515
+ end
516
+ end
517
+ end