atom-tools 0.9.0 → 2.0.5
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/COPYING +3 -3
- data/README +9 -49
- data/Rakefile +65 -62
- data/bin/atom-cp +159 -0
- data/bin/atom-grep +78 -0
- data/bin/atom-post +73 -0
- data/bin/atom-purge +82 -0
- data/doc/classes/Atom/AttrEl.html +163 -0
- data/doc/classes/Atom/Author.html +2 -19
- data/doc/classes/Atom/AutodiscoveryFailure.html +111 -0
- data/doc/classes/Atom/Categories.html +168 -0
- data/doc/classes/Atom/Category.html +10 -1
- data/doc/classes/Atom/Collection.html +194 -91
- data/doc/classes/Atom/Content.html +42 -1
- data/doc/classes/Atom/Contributor.html +2 -8
- data/doc/classes/Atom/Control.html +126 -0
- data/doc/classes/Atom/Converters.html +571 -0
- data/doc/classes/Atom/DigestAuth.html +285 -0
- data/doc/classes/Atom/Element.html +673 -106
- data/doc/classes/Atom/FileCache.html +287 -0
- data/doc/classes/Atom/HTTP.html +211 -95
- data/doc/classes/Atom/HTTPResponse.html +190 -0
- data/doc/classes/Atom/HasCategories.html +187 -0
- data/doc/classes/Atom/HasLinks.html +168 -0
- data/doc/classes/Atom/Link.html +80 -3
- data/doc/classes/Atom/NilCache.html +202 -0
- data/doc/classes/Atom/ParseError.html +111 -0
- data/doc/classes/Atom/Parsers.html +311 -0
- data/doc/classes/Atom/Person.html +130 -0
- data/doc/classes/Atom/Rights.html +113 -0
- data/doc/classes/Atom/Service.html +298 -0
- data/doc/{files/lib/atom/yaml_rb.html → classes/Atom/Source.html} +26 -24
- data/doc/classes/Atom/Subtitle.html +113 -0
- data/doc/classes/Atom/Summary.html +113 -0
- data/doc/classes/Atom/Text.html +196 -53
- data/doc/classes/Atom/Title.html +113 -0
- data/doc/classes/Atom/Tools.html +525 -0
- data/doc/classes/Atom/Workspace.html +121 -0
- data/doc/classes/Object.html +204 -0
- data/doc/created.rid +1 -1
- data/doc/files/README.html +9 -49
- data/doc/files/lib/atom/cache_rb.html +302 -0
- data/doc/files/lib/atom/collection_rb.html +1 -2
- data/doc/files/lib/atom/element_rb.html +2 -1
- data/doc/files/lib/atom/entry_rb.html +2 -2
- data/doc/files/lib/atom/feed_rb.html +1 -2
- data/doc/files/lib/atom/http_rb.html +6 -1
- data/doc/files/lib/atom/{xml_rb.html → service_rb.html} +8 -6
- data/doc/files/lib/atom/text_rb.html +2 -1
- data/doc/files/lib/atom/{app_rb.html → tools_rb.html} +4 -6
- data/doc/fr_class_index.html +23 -3
- data/doc/fr_file_index.html +3 -3
- data/doc/fr_method_index.html +111 -36
- data/lib/atom/cache.rb +178 -0
- data/lib/atom/collection.rb +90 -40
- data/lib/atom/element.rb +569 -161
- data/lib/atom/entry.rb +63 -89
- data/lib/atom/feed.rb +65 -67
- data/lib/atom/http.rb +421 -49
- data/lib/atom/service.rb +106 -0
- data/lib/atom/text.rb +138 -61
- data/lib/atom/tools.rb +163 -0
- data/spec/entry_spec.rb +364 -0
- data/spec/ext_spec.rb +42 -0
- data/spec/feed_spec.rb +39 -0
- data/spec/fixtures/contacts-feed.xml +34 -0
- data/spec/fixtures/entry-w-ext.xml +15 -0
- data/spec/fixtures/entry-w-xml.xml +24 -0
- data/spec/fixtures/entry.xml +42 -0
- data/spec/fixtures/feed-w-ext.xml +33 -0
- data/spec/fixtures/service-w-xhtml-ns.xml +21 -0
- data/spec/fixtures/service.xml +36 -0
- data/spec/service_spec.rb +108 -0
- data/spec/spec_helper.rb +9 -0
- data/test/conformance/order.rb +11 -10
- data/test/conformance/title.rb +9 -9
- data/test/conformance/updated.rb +2 -1
- data/test/runtests.rb +0 -0
- data/test/test_constructs.rb +78 -8
- data/test/test_feed.rb +35 -29
- data/test/test_general.rb +3 -30
- data/test/test_http.rb +248 -34
- data/test/test_protocol.rb +143 -24
- data/test/test_xml.rb +145 -53
- metadata +116 -62
- data/bin/atom-client.rb +0 -246
- data/bin/atom-server.rb~ +0 -71
- data/doc/classes/Atom/App.html +0 -217
- data/doc/classes/Atom/Entry.html +0 -365
- data/doc/classes/Atom/Feed.html +0 -585
- data/lib/atom/app.rb +0 -87
- data/lib/atom/xml.rb +0 -200
- data/lib/atom/yaml.rb +0 -101
data/test/test_http.rb
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
require "test/unit"
|
|
2
|
+
|
|
1
3
|
require "atom/http"
|
|
2
4
|
require "webrick"
|
|
3
5
|
|
|
4
|
-
class
|
|
6
|
+
class AtomHTTPTest < Test::Unit::TestCase
|
|
7
|
+
REALM = "test authentication"
|
|
8
|
+
USER = "test_user"
|
|
9
|
+
PASS = "aoeuaoeu"
|
|
10
|
+
|
|
11
|
+
# for Google AuthSub authentication
|
|
12
|
+
TOKEN = "pq7266382__838"
|
|
13
|
+
|
|
14
|
+
SECRET_DATA = "I kissed a boy once"
|
|
15
|
+
|
|
5
16
|
def setup
|
|
6
17
|
@http = Atom::HTTP.new
|
|
7
18
|
@port = rand(1024) + 1024
|
|
@@ -11,76 +22,279 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
|
11
22
|
end
|
|
12
23
|
|
|
13
24
|
def test_parse_wwwauth
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
# a Basic WWW-Authenticate
|
|
26
|
+
header = 'realm="SokEvo"'
|
|
27
|
+
|
|
28
|
+
params = @http.send :parse_quoted_wwwauth, header
|
|
29
|
+
assert_equal "SokEvo", params[:realm]
|
|
30
|
+
|
|
31
|
+
# Digest is parsed a bit differently
|
|
32
|
+
header = 'opaque="07UrfUiCYac5BbWJ", algorithm=MD5-sess, qop="auth", stale=TRUE, nonce="MDAx0Mzk", realm="test authentication"'
|
|
33
|
+
|
|
34
|
+
params = @http.send :parse_wwwauth_digest, header
|
|
18
35
|
|
|
19
|
-
assert_equal "
|
|
20
|
-
assert_equal "
|
|
36
|
+
assert_equal "test authentication", params[:realm]
|
|
37
|
+
assert_equal "MDAx0Mzk", params[:nonce]
|
|
38
|
+
assert_equal true, params[:stale]
|
|
39
|
+
assert_equal "auth", params[:qop]
|
|
40
|
+
assert_equal "MD5-sess", params[:algorithm]
|
|
41
|
+
assert_equal "07UrfUiCYac5BbWJ", params[:opaque]
|
|
21
42
|
end
|
|
22
43
|
|
|
23
44
|
def test_GET
|
|
24
|
-
|
|
45
|
+
mount_one_shot do |req,res|
|
|
25
46
|
assert_equal("/", req.path)
|
|
26
47
|
|
|
27
48
|
res.content_type = "text/plain"
|
|
28
|
-
res.body = "
|
|
29
|
-
|
|
30
|
-
@s.stop
|
|
49
|
+
res.body = "Success!"
|
|
31
50
|
end
|
|
32
51
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
res = get_root
|
|
52
|
+
get_root
|
|
36
53
|
|
|
37
|
-
assert_equal
|
|
38
|
-
assert_equal
|
|
39
|
-
assert_equal
|
|
54
|
+
assert_equal "200", @res.code
|
|
55
|
+
assert_equal "text/plain", @res.content_type
|
|
56
|
+
assert_equal "Success!", @res.body
|
|
40
57
|
end
|
|
41
58
|
|
|
42
59
|
def test_GET_headers
|
|
43
|
-
|
|
60
|
+
mount_one_shot do |req,res|
|
|
44
61
|
assert_equal("tester agent", req["User-Agent"])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
get_root("User-Agent" => "tester agent")
|
|
65
|
+
|
|
66
|
+
assert_equal "200", @res.code
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_redirect
|
|
70
|
+
@s.mount_proc("/") do |req,res|
|
|
71
|
+
res.status = 302
|
|
72
|
+
res["Location"] = "http://localhost:#{@port}/redirected"
|
|
45
73
|
|
|
74
|
+
res.body = "ignore me."
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@s.mount_proc("/redirected") do |req,res|
|
|
78
|
+
res.content_type = "text/plain"
|
|
79
|
+
res.body = "Success!"
|
|
80
|
+
|
|
46
81
|
@s.stop
|
|
47
82
|
end
|
|
48
83
|
|
|
84
|
+
one_shot; get_root
|
|
85
|
+
|
|
86
|
+
# the redirect should be transparent (to whatever extent it can be)
|
|
87
|
+
assert_equal "200", @res.code
|
|
88
|
+
assert_equal "Success!", @res.body
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_redirect_loop
|
|
92
|
+
@s.mount_proc("/") do |req,res|
|
|
93
|
+
res.status = 302
|
|
94
|
+
res["Location"] = "http://localhost:#{@port}/redirected"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
@s.mount_proc("/redirected") do |req,res|
|
|
98
|
+
res.status = 302
|
|
99
|
+
res["Location"] = "http://localhost:#{@port}/"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
one_shot
|
|
103
|
+
|
|
104
|
+
assert_raises(Atom::HTTPException) { get_root }
|
|
105
|
+
|
|
106
|
+
@s.stop
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_redirect_non_GET_non_HEAD
|
|
110
|
+
@s.mount_proc("/") do |req,res|
|
|
111
|
+
assert_equal "POST", req.request_method
|
|
112
|
+
res.status = 302
|
|
113
|
+
res["Location"] = "http://localhost:#{@port}/redirected"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
@s.mount_proc("/redirected") do |req,res|
|
|
117
|
+
assert_equal "POST", req.request_method
|
|
118
|
+
assert_equal "important message", req.body
|
|
119
|
+
res.content_type = "text/plain"
|
|
120
|
+
res.body = "Success!"
|
|
121
|
+
end
|
|
122
|
+
|
|
49
123
|
one_shot
|
|
50
124
|
|
|
51
|
-
res =
|
|
125
|
+
@res = @http.post "http://localhost:#{@port}/", "important message"
|
|
52
126
|
|
|
53
|
-
assert_equal
|
|
127
|
+
assert_equal "302", @res.code
|
|
128
|
+
|
|
129
|
+
@http.allow_all_redirects = true
|
|
130
|
+
|
|
131
|
+
one_shot
|
|
132
|
+
|
|
133
|
+
@res = @http.post "http://localhost:#{@port}/", "important message"
|
|
134
|
+
|
|
135
|
+
assert_equal "200", @res.code
|
|
136
|
+
assert_equal "Success!", @res.body
|
|
137
|
+
|
|
138
|
+
@s.stop
|
|
54
139
|
end
|
|
55
140
|
|
|
56
141
|
def test_basic_auth
|
|
57
|
-
|
|
58
|
-
WEBrick::HTTPAuth.basic_auth(req, res,
|
|
59
|
-
u ==
|
|
142
|
+
mount_one_shot do |req,res|
|
|
143
|
+
WEBrick::HTTPAuth.basic_auth(req, res, REALM) do |u,p|
|
|
144
|
+
u == USER and p == PASS
|
|
60
145
|
end
|
|
61
146
|
|
|
62
|
-
res.body =
|
|
63
|
-
@s.stop
|
|
147
|
+
res.body = SECRET_DATA
|
|
64
148
|
end
|
|
65
149
|
|
|
150
|
+
# no credentials
|
|
151
|
+
assert_raises(Atom::Unauthorized) { get_root }
|
|
152
|
+
|
|
153
|
+
# incorrect credentials
|
|
154
|
+
@http.user = USER
|
|
155
|
+
@http.pass = "incorrect_password"
|
|
156
|
+
|
|
66
157
|
one_shot
|
|
67
|
-
|
|
158
|
+
|
|
159
|
+
assert_raises(Atom::Unauthorized) { get_root }
|
|
160
|
+
|
|
161
|
+
# no credentials, fancy block
|
|
162
|
+
@http.when_auth do nil end
|
|
163
|
+
|
|
164
|
+
one_shot
|
|
165
|
+
|
|
68
166
|
assert_raises(Atom::Unauthorized) { get_root }
|
|
69
167
|
|
|
168
|
+
# correct credentials, fancy block
|
|
70
169
|
@http.when_auth do |abs_url,realm|
|
|
71
170
|
assert_equal "http://localhost:#{@port}/", abs_url
|
|
72
|
-
assert_equal
|
|
171
|
+
assert_equal REALM, realm
|
|
73
172
|
|
|
74
|
-
[
|
|
173
|
+
[USER, PASS]
|
|
75
174
|
end
|
|
76
|
-
|
|
175
|
+
|
|
77
176
|
one_shot
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
177
|
+
|
|
178
|
+
assert_authenticates
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def test_digest_auth
|
|
182
|
+
# a dummy userdb (saves me creating a file)
|
|
183
|
+
userdb = {}
|
|
184
|
+
# with a single entry
|
|
185
|
+
userdb[USER] = PASS
|
|
186
|
+
|
|
187
|
+
# HTTPAuth::DigestAuth#authenticate uses this
|
|
188
|
+
def userdb.get_passwd(realm, user, reload)
|
|
189
|
+
Digest::MD5::hexdigest([user, realm, self[user]].join(":"))
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
authenticator = WEBrick::HTTPAuth::DigestAuth.new(
|
|
193
|
+
:UserDB => userdb,
|
|
194
|
+
:Realm => REALM,
|
|
195
|
+
:Algorithm => "MD5"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
@s.mount_proc("/") do |req,res|
|
|
199
|
+
authenticator.authenticate(req, res)
|
|
200
|
+
res.body = SECRET_DATA
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
one_shot
|
|
204
|
+
|
|
205
|
+
# no credentials
|
|
206
|
+
assert_raises(Atom::Unauthorized) { get_root }
|
|
207
|
+
|
|
208
|
+
@http.user = USER
|
|
209
|
+
@http.pass = PASS
|
|
210
|
+
|
|
211
|
+
# correct credentials
|
|
212
|
+
assert_authenticates
|
|
213
|
+
|
|
214
|
+
@s.stop
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def test_wsse_auth
|
|
218
|
+
mount_one_shot do |req,res|
|
|
219
|
+
assert_equal 'WSSE profile="UsernameToken"', req["Authorization"]
|
|
220
|
+
|
|
221
|
+
xwsse = req["X-WSSE"]
|
|
222
|
+
|
|
223
|
+
p = @http.send :parse_quoted_wwwauth, xwsse
|
|
224
|
+
|
|
225
|
+
assert_equal USER, p[:Username]
|
|
226
|
+
assert_match /^UsernameToken /, xwsse
|
|
227
|
+
|
|
228
|
+
# Base64( SHA1( Nonce + CreationTimestamp + Password ) )
|
|
229
|
+
pd_string = p[:Nonce].unpack("m").first + p[:Created] + PASS
|
|
230
|
+
password_digest = [Digest::SHA1.digest(pd_string)].pack("m").chomp
|
|
231
|
+
|
|
232
|
+
assert_equal password_digest, p[:PasswordDigest]
|
|
233
|
+
|
|
234
|
+
res.body = SECRET_DATA
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
@http.always_auth = :wsse
|
|
238
|
+
@http.user = USER
|
|
239
|
+
@http.pass = PASS
|
|
240
|
+
|
|
241
|
+
assert_authenticates
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def test_authsub_auth
|
|
245
|
+
mount_one_shot do |req,res|
|
|
246
|
+
assert_equal %{AuthSub token="#{TOKEN}"}, req["Authorization"]
|
|
247
|
+
|
|
248
|
+
res.body = SECRET_DATA
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
@http.always_auth = :authsub
|
|
252
|
+
@http.token = TOKEN
|
|
253
|
+
|
|
254
|
+
assert_authenticates
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def test_multiple_auth
|
|
258
|
+
mount_one_shot do |req,res|
|
|
259
|
+
# WEBrick doesn't seem to support sending multiple headers, so this is the best we can do
|
|
260
|
+
res["WWW-Authenticate"] = %{NonexistantAuth parameter="yes", qop="auth", Basic realm="#{REALM}", something="true"}
|
|
261
|
+
|
|
262
|
+
if req["Authorization"]
|
|
263
|
+
res.body = SECRET_DATA
|
|
264
|
+
else
|
|
265
|
+
res.status = 401
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
@http.user = USER
|
|
270
|
+
@http.pass = PASS
|
|
271
|
+
|
|
272
|
+
assert_authenticates
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# mount a block on the test server, shutting the server down after a
|
|
276
|
+
# single request
|
|
277
|
+
def mount_one_shot &block
|
|
278
|
+
@s.mount_proc("/") do |req,res|
|
|
279
|
+
block.call req, res
|
|
280
|
+
@s.stop
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
one_shot
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# test that we authenticated properly
|
|
287
|
+
def assert_authenticates
|
|
288
|
+
get_root
|
|
289
|
+
assert_equal "200", @res.code
|
|
290
|
+
assert_equal SECRET_DATA, @res.body
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# performs a GET on the test server
|
|
294
|
+
def get_root(*args)
|
|
295
|
+
@res = @http.get("http://localhost:#{@port}/", *args)
|
|
82
296
|
end
|
|
83
297
|
|
|
84
|
-
|
|
298
|
+
# sets up the server for a single request
|
|
85
299
|
def one_shot; Thread.new { @s.start }; end
|
|
86
300
|
end
|
data/test/test_protocol.rb
CHANGED
|
@@ -1,28 +1,47 @@
|
|
|
1
1
|
require "test/unit"
|
|
2
2
|
|
|
3
|
-
require "atom/
|
|
3
|
+
require "atom/service"
|
|
4
|
+
|
|
5
|
+
# needed for hpricot
|
|
6
|
+
require "rubygems"
|
|
4
7
|
|
|
5
8
|
class FakeHTTP
|
|
6
9
|
Response = Struct.new(:body, :code, :content_type)
|
|
7
10
|
|
|
8
|
-
def initialize table
|
|
11
|
+
def initialize table
|
|
9
12
|
@table = table
|
|
10
|
-
@mime_type = mime_type
|
|
11
13
|
end
|
|
12
|
-
|
|
14
|
+
|
|
15
|
+
def get url, headers = {}
|
|
13
16
|
res = Response.new
|
|
14
|
-
|
|
17
|
+
|
|
18
|
+
data = @table[url.to_s]
|
|
19
|
+
|
|
20
|
+
res.body = data[1]
|
|
15
21
|
res.code = 200.to_s
|
|
16
|
-
res.content_type =
|
|
22
|
+
res.content_type = data[0]
|
|
23
|
+
|
|
24
|
+
def res.validate_content_type valid; valid.member? content_type; end
|
|
25
|
+
|
|
17
26
|
res
|
|
18
27
|
end
|
|
19
28
|
end
|
|
20
29
|
|
|
21
30
|
class AtomProtocolTest < Test::Unit::TestCase
|
|
22
|
-
|
|
31
|
+
attr_reader :have_hpricot
|
|
32
|
+
|
|
33
|
+
def initialize *args
|
|
34
|
+
super
|
|
35
|
+
|
|
36
|
+
require "hpricot"
|
|
37
|
+
@have_hpricot = true
|
|
38
|
+
rescue LoadError
|
|
39
|
+
puts "skipping hpricot tests"
|
|
40
|
+
end
|
|
23
41
|
|
|
24
|
-
|
|
25
|
-
|
|
42
|
+
def test_introspection
|
|
43
|
+
doc = <<END
|
|
44
|
+
<service xmlns="http://www.w3.org/2007/app"
|
|
26
45
|
xmlns:atom="http://www.w3.org/2005/Atom">
|
|
27
46
|
<workspace>
|
|
28
47
|
<atom:title>My Blog</atom:title>
|
|
@@ -36,23 +55,79 @@ class AtomProtocolTest < Test::Unit::TestCase
|
|
|
36
55
|
</workspace>
|
|
37
56
|
</service>
|
|
38
57
|
END
|
|
39
|
-
|
|
40
|
-
http = FakeHTTP.new({ "http://example.com/service.xml" => service }, "application/atomserv+xml")
|
|
41
58
|
|
|
59
|
+
service = Atom::Service.parse doc
|
|
42
60
|
|
|
43
|
-
|
|
61
|
+
ws = service.workspaces.first
|
|
62
|
+
assert_equal "My Blog", ws.title.to_s
|
|
44
63
|
|
|
45
|
-
coll =
|
|
46
|
-
assert_equal
|
|
47
|
-
assert_equal
|
|
48
|
-
assert_equal
|
|
64
|
+
coll = ws.collections.first
|
|
65
|
+
assert_equal "http://example.org/myblog/entries", coll.href
|
|
66
|
+
assert_equal "Entries", coll.title.to_s
|
|
67
|
+
assert_equal ["application/atom+xml;type=entry"], coll.accepts
|
|
49
68
|
|
|
50
|
-
coll =
|
|
51
|
-
assert_equal
|
|
52
|
-
assert_equal
|
|
53
|
-
assert_equal
|
|
69
|
+
coll = ws.collections.last
|
|
70
|
+
assert_equal "http://example.org/myblog/fotes", coll.href
|
|
71
|
+
assert_equal "Photos", coll.title.to_s
|
|
72
|
+
assert_equal ["image/*"], coll.accepts
|
|
54
73
|
|
|
55
|
-
|
|
74
|
+
http = service.instance_variable_get(:@http)
|
|
75
|
+
assert_instance_of Atom::HTTP, http
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_write_introspection
|
|
79
|
+
service = Atom::Service.new
|
|
80
|
+
|
|
81
|
+
ws = service.workspaces.new
|
|
82
|
+
|
|
83
|
+
ws.title = "Workspace 1"
|
|
84
|
+
|
|
85
|
+
coll = Atom::Collection.new "http://example.org/entries"
|
|
86
|
+
coll.title = "Entries"
|
|
87
|
+
ws.collections << coll
|
|
88
|
+
|
|
89
|
+
coll = Atom::Collection.new "http://example.org/audio"
|
|
90
|
+
coll.title = "Audio"
|
|
91
|
+
coll.accepts = ["audio/*"]
|
|
92
|
+
ws.collections << coll
|
|
93
|
+
|
|
94
|
+
nses = { "app" => Atom::PP_NS, "atom" => Atom::NS }
|
|
95
|
+
|
|
96
|
+
doc = REXML::Document.new(service.to_s)
|
|
97
|
+
|
|
98
|
+
assert_equal "http://www.w3.org/2007/app", doc.root.namespace
|
|
99
|
+
|
|
100
|
+
ws = REXML::XPath.first( doc.root,
|
|
101
|
+
"/app:service/app:workspace",
|
|
102
|
+
nses )
|
|
103
|
+
|
|
104
|
+
title = REXML::XPath.first( ws, "./atom:title", nses)
|
|
105
|
+
|
|
106
|
+
assert_equal "Workspace 1", title.text
|
|
107
|
+
assert_equal "http://www.w3.org/2005/Atom", title.namespace
|
|
108
|
+
|
|
109
|
+
colls = REXML::XPath.match( ws, "./app:collection", nses)
|
|
110
|
+
assert_equal(2, colls.length)
|
|
111
|
+
|
|
112
|
+
entries = colls.first
|
|
113
|
+
|
|
114
|
+
assert_equal "http://example.org/entries", entries.attributes["href"]
|
|
115
|
+
|
|
116
|
+
title = REXML::XPath.first(entries, "./atom:title", nses)
|
|
117
|
+
assert_equal "Entries", title.text
|
|
118
|
+
|
|
119
|
+
accepts = REXML::XPath.first(entries, "./app:accept", nses)
|
|
120
|
+
assert_nil accepts
|
|
121
|
+
|
|
122
|
+
audio = colls.last
|
|
123
|
+
|
|
124
|
+
assert_equal "http://example.org/audio", audio.attributes["href"]
|
|
125
|
+
|
|
126
|
+
title = REXML::XPath.first(audio, "./atom:title", nses)
|
|
127
|
+
assert_equal "Audio", title.text
|
|
128
|
+
|
|
129
|
+
accepts = REXML::XPath.first(audio, "./app:accept", nses)
|
|
130
|
+
assert_equal "audio/*", accepts.text
|
|
56
131
|
end
|
|
57
132
|
|
|
58
133
|
def test_dont_specify_http_object
|
|
@@ -61,9 +136,53 @@ END
|
|
|
61
136
|
assert_instance_of Atom::HTTP, collection.instance_variable_get("@http")
|
|
62
137
|
end
|
|
63
138
|
|
|
64
|
-
def
|
|
65
|
-
|
|
139
|
+
def test_autodiscover_service_link
|
|
140
|
+
return unless have_hpricot
|
|
141
|
+
|
|
142
|
+
http = FakeHTTP.new \
|
|
143
|
+
'http://example.org/' => [ 'text/html', '<html><link rel="service" href="svc">' ],
|
|
144
|
+
'http://example.org/xhtml' => [ 'text/html', '<html><head><link rel="service" href="svc"/></head></html>' ],
|
|
145
|
+
'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ]
|
|
146
|
+
|
|
147
|
+
svc = Atom::Service.discover 'http://example.org/', http
|
|
148
|
+
assert_instance_of Atom::Service, svc
|
|
149
|
+
|
|
150
|
+
svc = Atom::Service.discover 'http://example.org/xhtml', http
|
|
151
|
+
assert_instance_of Atom::Service, svc
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_autodiscover_rsd
|
|
155
|
+
return unless have_hpricot
|
|
156
|
+
|
|
157
|
+
http = FakeHTTP.new \
|
|
158
|
+
'http://example.org/' => [ 'text/html', '<html><link rel="EditURI" href="rsd">' ],
|
|
159
|
+
'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ],
|
|
160
|
+
'http://example.org/rsd' => [ 'text/xml', '<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd"><service><apis><api name="Atom" apiLink="svc" /></apis></service></rsd>' ]
|
|
161
|
+
|
|
162
|
+
svc = Atom::Service.discover 'http://example.org/', http
|
|
163
|
+
assert_instance_of Atom::Service, svc
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def test_autodiscover_conneg
|
|
167
|
+
http = FakeHTTP.new \
|
|
168
|
+
'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ]
|
|
169
|
+
|
|
170
|
+
svc = Atom::Service.discover 'http://example.org/svc', http
|
|
171
|
+
assert_instance_of Atom::Service, svc
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_cant_autodiscover
|
|
175
|
+
return unless have_hpricot
|
|
176
|
+
|
|
177
|
+
http = FakeHTTP.new 'http://example.org/h' => [ 'text/html', '<html>' ],
|
|
178
|
+
'http://example.org/t' => [ 'text/plain', 'no joy.' ]
|
|
179
|
+
|
|
180
|
+
assert_raises Atom::AutodiscoveryFailure do
|
|
181
|
+
Atom::Service.discover 'http://example.org/h', http
|
|
182
|
+
end
|
|
66
183
|
|
|
67
|
-
|
|
184
|
+
assert_raises Atom::AutodiscoveryFailure do
|
|
185
|
+
Atom::Service.discover 'http://example.org/t', http
|
|
186
|
+
end
|
|
68
187
|
end
|
|
69
188
|
end
|