thehack-atom-tools 2.0.3

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.
@@ -0,0 +1,168 @@
1
+ require "test/unit"
2
+
3
+ require "atom/service"
4
+
5
+ class FakeHTTP
6
+ Response = Struct.new(:body, :code, :content_type)
7
+
8
+ def initialize table
9
+ @table = table
10
+ end
11
+
12
+ def get url, headers = {}
13
+ res = Response.new
14
+
15
+ data = @table[url.to_s]
16
+
17
+ res.body = data[1]
18
+ res.code = 200.to_s
19
+ res.content_type = data[0]
20
+
21
+ def res.validate_content_type valid; valid.member? content_type; end
22
+
23
+ res
24
+ end
25
+ end
26
+
27
+ class AtomProtocolTest < Test::Unit::TestCase
28
+ def test_introspection
29
+ doc = <<END
30
+ <service xmlns="http://www.w3.org/2007/app"
31
+ xmlns:atom="http://www.w3.org/2005/Atom">
32
+ <workspace>
33
+ <atom:title>My Blog</atom:title>
34
+ <collection href="http://example.org/myblog/entries">
35
+ <atom:title>Entries</atom:title>
36
+ </collection>
37
+ <collection href="http://example.org/myblog/fotes">
38
+ <atom:title>Photos</atom:title>
39
+ <accept>image/*</accept>
40
+ </collection>
41
+ </workspace>
42
+ </service>
43
+ END
44
+
45
+ service = Atom::Service.parse doc
46
+
47
+ ws = service.workspaces.first
48
+ assert_equal "My Blog", ws.title.to_s
49
+
50
+ coll = ws.collections.first
51
+ assert_equal "http://example.org/myblog/entries", coll.href
52
+ assert_equal "Entries", coll.title.to_s
53
+ assert_equal ["application/atom+xml;type=entry"], coll.accepts
54
+
55
+ coll = ws.collections.last
56
+ assert_equal "http://example.org/myblog/fotes", coll.href
57
+ assert_equal "Photos", coll.title.to_s
58
+ assert_equal ["image/*"], coll.accepts
59
+
60
+ http = service.instance_variable_get(:@http)
61
+ assert_instance_of Atom::HTTP, http
62
+ end
63
+
64
+ def test_write_introspection
65
+ service = Atom::Service.new
66
+
67
+ ws = service.workspaces.new
68
+
69
+ ws.title = "Workspace 1"
70
+
71
+ coll = Atom::Collection.new "http://example.org/entries"
72
+ coll.title = "Entries"
73
+ ws.collections << coll
74
+
75
+ coll = Atom::Collection.new "http://example.org/audio"
76
+ coll.title = "Audio"
77
+ coll.accepts = ["audio/*"]
78
+ ws.collections << coll
79
+
80
+ nses = { "app" => Atom::PP_NS, "atom" => Atom::NS }
81
+
82
+ doc = REXML::Document.new(service.to_s)
83
+
84
+ assert_equal "http://www.w3.org/2007/app", doc.root.namespace
85
+
86
+ ws = REXML::XPath.first( doc.root,
87
+ "/app:service/app:workspace",
88
+ nses )
89
+
90
+ title = REXML::XPath.first( ws, "./atom:title", nses)
91
+
92
+ assert_equal "Workspace 1", title.text
93
+ assert_equal "http://www.w3.org/2005/Atom", title.namespace
94
+
95
+ colls = REXML::XPath.match( ws, "./app:collection", nses)
96
+ assert_equal(2, colls.length)
97
+
98
+ entries = colls.first
99
+
100
+ assert_equal "http://example.org/entries", entries.attributes["href"]
101
+
102
+ title = REXML::XPath.first(entries, "./atom:title", nses)
103
+ assert_equal "Entries", title.text
104
+
105
+ accepts = REXML::XPath.first(entries, "./app:accept", nses)
106
+ assert_nil accepts
107
+
108
+ audio = colls.last
109
+
110
+ assert_equal "http://example.org/audio", audio.attributes["href"]
111
+
112
+ title = REXML::XPath.first(audio, "./atom:title", nses)
113
+ assert_equal "Audio", title.text
114
+
115
+ accepts = REXML::XPath.first(audio, "./app:accept", nses)
116
+ assert_equal "audio/*", accepts.text
117
+ end
118
+
119
+ def test_dont_specify_http_object
120
+ collection = Atom::Collection.new("http://necronomicorp.com/testatom?atom")
121
+
122
+ assert_instance_of Atom::HTTP, collection.instance_variable_get("@http")
123
+ end
124
+
125
+ def test_autodiscover_service_link
126
+ http = FakeHTTP.new \
127
+ 'http://example.org/' => [ 'text/html', '<html><link rel="service" href="svc">' ],
128
+ 'http://example.org/xhtml' => [ 'text/html', '<html><head><link rel="service" href="svc"/></head></html>' ],
129
+ 'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ]
130
+
131
+ svc = Atom::Service.discover 'http://example.org/', http
132
+ assert_instance_of Atom::Service, svc
133
+
134
+ svc = Atom::Service.discover 'http://example.org/xhtml', http
135
+ assert_instance_of Atom::Service, svc
136
+ end
137
+
138
+ def test_autodiscover_rsd
139
+ http = FakeHTTP.new \
140
+ 'http://example.org/' => [ 'text/html', '<html><link rel="EditURI" href="rsd">' ],
141
+ 'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ],
142
+ '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>' ]
143
+
144
+ svc = Atom::Service.discover 'http://example.org/', http
145
+ assert_instance_of Atom::Service, svc
146
+ end
147
+
148
+ def test_autodiscover_conneg
149
+ http = FakeHTTP.new \
150
+ 'http://example.org/svc' => [ 'application/atomsvc+xml', '<service xmlns="http://www.w3.org/2007/app"/>' ]
151
+
152
+ svc = Atom::Service.discover 'http://example.org/svc', http
153
+ assert_instance_of Atom::Service, svc
154
+ end
155
+
156
+ def test_cant_autodiscover
157
+ http = FakeHTTP.new 'http://example.org/h' => [ 'text/html', '<html>' ],
158
+ 'http://example.org/t' => [ 'text/plain', 'no joy.' ]
159
+
160
+ assert_raises Atom::AutodiscoveryFailure do
161
+ Atom::Service.discover 'http://example.org/h', http
162
+ end
163
+
164
+ assert_raises Atom::AutodiscoveryFailure do
165
+ Atom::Service.discover 'http://example.org/t', http
166
+ end
167
+ end
168
+ end
data/test/test_xml.rb ADDED
@@ -0,0 +1,445 @@
1
+ $:.unshift 'lib/', File.dirname(__FILE__) + '/../lib'
2
+ require "test/unit"
3
+ require "atom/service"
4
+
5
+ class AtomTest < Test::Unit::TestCase
6
+ def test_text_type_text
7
+ entry = get_entry
8
+
9
+ entry.title = "Let's talk about <html>"
10
+ assert_equal("text", entry.title["type"])
11
+
12
+ assert_match('&lt;', entry.title.xml.to_s)
13
+
14
+ xml = entry.to_xml
15
+
16
+ b = Atom::Entry.parse(xml).to_s
17
+
18
+ base_check xml
19
+
20
+ assert_equal("Let's talk about <html>", xml.elements["title"].text)
21
+
22
+ assert_match('&lt;', entry.to_s)
23
+ end
24
+
25
+ def test_text_type_html
26
+ entry = get_entry
27
+
28
+ entry.title = "Atom-drunk pirates<br>run amok!"
29
+ entry.title["type"] = "html"
30
+
31
+ xml = get_elements entry
32
+
33
+ assert_equal("Atom-drunk pirates<br>run amok!", xml.elements["title"].text)
34
+ assert_equal("html", xml.elements["title"].attributes["type"])
35
+
36
+ assert_match('&lt;', entry.to_s)
37
+ end
38
+
39
+ def test_text_type_xhtml
40
+ entry = get_entry
41
+
42
+ entry.title = "Atom-drunk pirates <em>run amok</em>!"
43
+ entry.title["type"] = "xhtml"
44
+
45
+ xml = get_elements entry
46
+
47
+ assert_equal(XHTML::NS, xml.elements["title/div"].namespace)
48
+ assert_equal("run amok", xml.elements["title/div/em"].text)
49
+
50
+ assert_match('<em>', entry.to_s)
51
+ end
52
+
53
+ def test_html_text_with_entities
54
+ entry = get_entry
55
+
56
+ entry.title = "Atoms discovered to be smaller than 1&mu;m"
57
+ entry.title["type"] = "html"
58
+
59
+ assert_match(/&amp;mu;/, entry.to_s)
60
+ end
61
+
62
+ def test_author
63
+ entry = get_entry
64
+ a = entry.authors.new
65
+
66
+ a.name= "Brendan Taylor"
67
+ a.uri = "http://necronomicorp.com/blog/"
68
+
69
+ xml = get_elements entry
70
+
71
+ assert_equal("http://necronomicorp.com/blog/", xml.elements["author/uri"].text)
72
+ assert_equal("Brendan Taylor", xml.elements["author/name"].text)
73
+ assert_nil(xml.elements["author/email"])
74
+ end
75
+
76
+ def test_tags
77
+ entry = get_entry
78
+ entry.tag_with "test tags"
79
+
80
+ xml = get_elements entry
81
+
82
+ assert_has_category(xml, "test")
83
+ assert_has_category(xml, "tags")
84
+ end
85
+
86
+ def test_updated
87
+ entry = get_entry
88
+ entry.updated = "1970-01-01"
89
+ entry.content = "blah"
90
+
91
+ assert entry.updated.is_a?(Time)
92
+
93
+ xml = entry.to_xml
94
+
95
+ b = Atom::Entry.parse(xml).to_s
96
+
97
+ base_check xml
98
+
99
+ assert_match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/, xml.elements["updated"].text, "atom:updated isn't in xsd:datetime format")
100
+
101
+ entry.updated!
102
+
103
+ assert((Time.parse("1970-01-01") < entry.updated), "<updated/> is not updated")
104
+ end
105
+
106
+ def test_edited
107
+ entry = get_entry
108
+
109
+ assert_nil entry.edited
110
+
111
+ entry.edited = "1990-04-07"
112
+ assert entry.edited.is_a?(Time)
113
+
114
+ xml = get_elements entry
115
+ assert_equal(Atom::PP_NS, xml.elements["app:edited"].namespace)
116
+ assert_match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/, xml.elements["app:edited"].text,
117
+ "atom:edited isn't in xsd:datetime format")
118
+
119
+ entry.edited!
120
+ assert((Time.parse("1990-04-07") < entry.edited), "<edited/> is not updated")
121
+ end
122
+
123
+ def test_out_of_line
124
+ entry = get_entry
125
+
126
+ entry.content = "this shouldn't appear"
127
+ entry.content["src"] = 'http://example.org/test.png'
128
+ entry.content["type"] = "image/png"
129
+
130
+ xml = get_elements(entry)
131
+
132
+ assert_nil xml.elements["content"].text
133
+ assert_equal("http://example.org/test.png", xml.elements["content"].attributes["src"])
134
+ assert_equal("image/png", xml.elements["content"].attributes["type"])
135
+ end
136
+
137
+ def test_extensions
138
+ entry = get_entry
139
+
140
+ assert(entry.extensions.empty?)
141
+
142
+ element = REXML::Element.new("test")
143
+ element.add_namespace "http://purl.org/"
144
+
145
+ entry.extensions << element
146
+
147
+ assert entry.extensions.member?(element)
148
+
149
+ xml = get_elements entry
150
+
151
+ assert_equal(REXML::Element, xml.elements["test"].class)
152
+ assert_equal("http://purl.org/", xml.elements["test"].namespace)
153
+ end
154
+
155
+ def test_roundtrip_extension
156
+ entry = Atom::Entry.parse("<entry xmlns='http://www.w3.org/2005/Atom' xmlns:nil='http://necronomicorp.com/nil'><nil:ext/></entry>")
157
+
158
+ assert_match(/xmlns:nil='http:\/\/necronomicorp.com\/nil'/, entry.to_s)
159
+ end
160
+
161
+ def test_app_control
162
+ entry = get_entry
163
+
164
+ assert !entry.draft
165
+
166
+ assert_nil get_elements(entry).elements["control"]
167
+
168
+ entry.draft = true
169
+
170
+ xml = get_elements entry
171
+
172
+ assert_equal Atom::PP_NS, xml.elements["app:control"].namespace
173
+ assert_equal Atom::PP_NS, xml.elements["app:control/app:draft"].namespace
174
+ assert_equal "yes", xml.elements["app:control/app:draft"].text
175
+
176
+ entry2 = Atom::Entry.parse xml
177
+
178
+ assert entry.draft
179
+ end
180
+
181
+ def test_extensive_entry_parsing
182
+ str = '<entry xmlns="http://www.w3.org/2005/Atom">
183
+ <title>Atom draft-07 snapshot</title>
184
+ <link rel="alternate" type="text/html"
185
+ href="http://example.org/2005/04/02/atom"/>
186
+ <link rel="enclosure" type="audio/mpeg" length="1337"
187
+ href="http://example.org/audio/ph34r_my_podcast.mp3"/>
188
+ <id>tag:example.org,2003:3.2397</id>
189
+ <updated>2005-07-31T12:29:29Z</updated>
190
+ <published>2003-12-13T08:29:29-04:00</published>
191
+ <author>
192
+ <name>Mark Pilgrim</name>
193
+ <uri>http://example.org/</uri>
194
+ <email>f8dy@example.com</email>
195
+ </author>
196
+ <contributor>
197
+ <name>Sam Ruby</name>
198
+ </contributor>
199
+ <contributor>
200
+ <name>Joe Gregorio</name>
201
+ </contributor>
202
+ <content type="xhtml" xml:lang="en"
203
+ xml:base="http://diveintomark.org/">
204
+ <div xmlns="http://www.w3.org/1999/xhtml">
205
+ <p><i>[Update: The Atom draft is finished.]</i></p>
206
+ </div>
207
+ </content>
208
+ </entry>'
209
+
210
+ entry = Atom::Entry.parse(str)
211
+
212
+ assert_equal("Atom draft-07 snapshot", entry.title.to_s)
213
+ assert_equal("tag:example.org,2003:3.2397", entry.id)
214
+
215
+ assert_equal(Time.parse("2005-07-31T12:29:29Z"), entry.updated)
216
+ assert_equal(Time.parse("2003-12-13T08:29:29-04:00"), entry.published)
217
+
218
+ assert_equal(2, entry.links.length)
219
+ assert_equal("alternate", entry.links.first["rel"])
220
+ assert_equal("text/html", entry.links.first["type"])
221
+ assert_equal("http://example.org/2005/04/02/atom", entry.links.first["href"])
222
+
223
+ assert_equal("enclosure", entry.links.last["rel"])
224
+ assert_equal("audio/mpeg", entry.links.last["type"])
225
+ assert_equal("1337", entry.links.last["length"])
226
+ assert_equal("http://example.org/audio/ph34r_my_podcast.mp3", entry.links.last["href"])
227
+
228
+ assert_equal(1, entry.authors.length)
229
+ assert_equal("Mark Pilgrim", entry.authors.first.name)
230
+ assert_equal("http://example.org/", entry.authors.first.uri)
231
+ assert_equal("f8dy@example.com", entry.authors.first.email)
232
+
233
+ assert_equal(2, entry.contributors.length)
234
+ assert_equal("Sam Ruby", entry.contributors.first.name)
235
+ assert_equal("Joe Gregorio", entry.contributors.last.name)
236
+
237
+ assert_equal("xhtml", entry.content["type"])
238
+
239
+ assert_match("<p><i>[Update: The Atom draft is finished.]</i></p>",
240
+ entry.content.to_s)
241
+
242
+ assert_equal("http://diveintomark.org/", entry.content.base)
243
+ # XXX unimplemented
244
+ # assert_equal("en", entry.content.lang)
245
+ end
246
+
247
+ def test_extensive_feed_parsing
248
+ feed = <<END
249
+ <?xml version="1.0" encoding="utf-8"?>
250
+ <feed xmlns="http://www.w3.org/2005/Atom">
251
+ <title type="text">dive into mark</title>
252
+ <subtitle type="html">
253
+ A &lt;em&gt;lot&lt;/em&gt; of effort
254
+ went into making this effortless
255
+ </subtitle>
256
+ <updated>2005-07-31T12:29:29Z</updated>
257
+ <id>tag:example.org,2003:3</id>
258
+ <link rel="alternate" type="text/html"
259
+ hreflang="en" href="http://example.org/"/>
260
+ <link rel="self" type="application/atom+xml"
261
+ href="http://example.org/feed.atom"/>
262
+ <rights>Copyright (c) 2003, Mark Pilgrim</rights>
263
+ <generator uri="http://www.example.com/" version="1.0">
264
+ Example Toolkit
265
+ </generator>
266
+ <entry>
267
+ <title>Atom draft-07 snapshot</title>
268
+ <author>
269
+ <name>Mark Pilgrim</name>
270
+ <uri>http://example.org/</uri>
271
+ <email>f8dy@example.com</email>
272
+ </author>
273
+ <link rel="alternate" type="text/html"
274
+ href="http://example.org/2005/04/02/atom"/>
275
+ <id>tag:example.org,2003:3.2397</id>
276
+ <updated>2005-07-31T12:29:29Z</updated>
277
+ </entry>
278
+ </feed>
279
+ END
280
+
281
+ feed = Atom::Feed.parse(feed)
282
+
283
+ assert_equal("", feed.base)
284
+
285
+ assert_equal("text", feed.title["type"])
286
+ assert_equal("dive into mark", feed.title.to_s)
287
+
288
+ assert_equal("html", feed.subtitle["type"])
289
+ assert_equal("\n A <em>lot</em> of effort\n went into making this effortless\n ", feed.subtitle.to_s)
290
+
291
+ assert_equal(Time.parse("2005-07-31T12:29:29Z"), feed.updated)
292
+ assert_equal("tag:example.org,2003:3", feed.id)
293
+
294
+ assert_equal([], feed.authors)
295
+
296
+ alt = feed.links.find { |l| l["rel"] == "alternate" }
297
+ assert_equal("alternate", alt["rel"])
298
+ assert_equal("text/html", alt["type"])
299
+ assert_equal("en", alt["hreflang"])
300
+ assert_equal("http://example.org/", alt["href"])
301
+
302
+ assert_equal("text", feed.rights["type"])
303
+ assert_equal("Copyright (c) 2003, Mark Pilgrim", feed.rights.to_s)
304
+
305
+ assert_equal("\n Example Toolkit\n ", feed.generator)
306
+ # XXX unimplemented
307
+ # assert_equal("http://www.example.com/", feed.generator["uri"])
308
+ # assert_equal("1.0", feed.generator["version"])
309
+
310
+ assert_equal(1, feed.entries.length)
311
+ assert_equal "Atom draft-07 snapshot", feed.entries.first.title.to_s
312
+ end
313
+
314
+ def test_parse_html_content
315
+ xml = <<END
316
+ <entry xmlns="http://www.w3.org/2005/Atom">
317
+ <summary type="html">
318
+ &lt;p>...&amp;amp; as a result of this, I submit that &lt;var>pi&lt;/var> &amp;lt; 4
319
+ </summary>
320
+ </entry>
321
+ END
322
+
323
+ entry = Atom::Entry.parse(xml)
324
+
325
+ assert_equal "html", entry.summary["type"]
326
+ assert_equal "<p>...&amp; as a result of this, I submit that <var>pi</var> &lt; 4", entry.summary.html.strip
327
+ end
328
+
329
+ def test_parse_goofy_entries
330
+ xml = <<END
331
+ <entry xmlns="http://www.w3.org/2005/Atom">
332
+ <content type="html"></content>
333
+ </entry>
334
+ END
335
+
336
+ entry = Atom::Entry.parse(xml)
337
+
338
+ assert_equal("", entry.content.to_s)
339
+ end
340
+
341
+ def test_parse_outofline_content
342
+ xml = <<END
343
+ <entry xmlns="http://www.w3.org/2005/Atom">
344
+ <content src="http://necronomicorp.com/nil">
345
+ src means empty content.
346
+ </content>
347
+ </entry>
348
+ END
349
+
350
+ entry = Atom::Entry.parse xml
351
+
352
+ assert_equal "http://necronomicorp.com/nil", entry.content["src"]
353
+ assert_equal "", entry.content.to_s
354
+ end
355
+
356
+ def test_serialize_base
357
+ entry = Atom::Entry.new
358
+
359
+ entry.base = "http://necronomicorp.com/nil"
360
+
361
+ base = get_elements(entry).root.attributes["xml:base"]
362
+ assert_equal "http://necronomicorp.com/nil", base
363
+
364
+ entry.base = URI.parse("http://necronomicorp.com/nil")
365
+
366
+ base = get_elements(entry).root.attributes["xml:base"]
367
+ assert_equal "http://necronomicorp.com/nil", base
368
+ end
369
+
370
+ def test_relative_base
371
+ base_url = "http://www.tbray.org/ongoing/ongoing.atom"
372
+ doc = "<entry xmlns='http://www.w3.org/2005/Atom' xml:base='When/200x/2006/10/11/'/>"
373
+
374
+ entry = Atom::Entry.parse(doc, base_url)
375
+ assert_equal("http://www.tbray.org/ongoing/When/200x/2006/10/11/", entry.base)
376
+ end
377
+
378
+ def test_relative_src
379
+ base_url = "http://example.org/foo/"
380
+ doc = "<entry xmlns='http://www.w3.org/2005/Atom'><content src='./bar'/></entry>"
381
+
382
+ entry = Atom::Entry.parse(doc, base_url)
383
+ assert_equal("http://example.org/foo/bar", entry.content['src'])
384
+ end
385
+
386
+ def test_edit_url
387
+ doc = <<END
388
+ <entry xmlns="http://www.w3.org/2005/Atom"><link rel="edit"/></entry>
389
+ END
390
+ entry = Atom::Entry.parse(doc)
391
+
392
+ assert_nil(entry.edit_url)
393
+
394
+ doc = <<END
395
+ <entry xmlns="http://www.w3.org/2005/Atom"><link rel="edit"/></entry>
396
+ END
397
+
398
+ entry = Atom::Entry.parse(doc)
399
+
400
+ assert_nil(entry.edit_url)
401
+
402
+ doc = <<END
403
+ <entry xmlns="http://www.w3.org/2005/Atom">
404
+ <link rel="edit" href="http://necronomicorp.com/nil"/>
405
+ </entry>
406
+ END
407
+
408
+ entry = Atom::Entry.parse(doc)
409
+
410
+ assert_equal("http://necronomicorp.com/nil", entry.edit_url)
411
+
412
+ entry.edit_url = "http://necronomicorp.com/foo"
413
+ assert_equal "http://necronomicorp.com/foo", entry.edit_url
414
+ end
415
+
416
+ def assert_has_category xml, term
417
+ assert_not_nil(REXML::XPath.match(xml, "/entry/category[@term = #{term}]"))
418
+ end
419
+
420
+ def assert_has_content_type xml, type
421
+ assert_equal(type, xml.elements["content"].attributes["type"])
422
+ end
423
+
424
+ def get_entry
425
+ Atom::Entry.new
426
+ end
427
+
428
+ # round-trips it to make sure things stay the same
429
+ def get_elements entry
430
+ xml = entry.to_xml
431
+
432
+ b = Atom::Entry.parse(xml)
433
+
434
+ assert_equal(xml.to_s, b.to_s)
435
+
436
+ base_check xml
437
+
438
+ xml
439
+ end
440
+
441
+ def base_check xml
442
+ assert_equal("entry", xml.root.name)
443
+ assert_equal("http://www.w3.org/2005/Atom", xml.root.namespace)
444
+ end
445
+ end