atom-tools 1.0.0 → 2.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.
@@ -24,9 +24,9 @@ END
24
24
  xhtml = entry.content.xml
25
25
 
26
26
  # Hpricot is imperfect; for now I'll just test that it's parseable
27
- assert_instance_of Array, xhtml
28
- assert_instance_of REXML::Element, xhtml.first
29
-
27
+ assert_instance_of REXML::Element, xhtml
28
+ assert_equal 'div', xhtml.name
29
+
30
30
  =begin
31
31
  assert_equal 2, xhtml.length
32
32
 
@@ -73,7 +73,7 @@ END
73
73
  assert_equal "html", entry.title["type"]
74
74
  assert_equal "<3", entry.title.to_s
75
75
  assert_equal "&lt;3", entry.title.html
76
-
76
+
77
77
  title = entry.to_xml.root.children.first
78
78
  assert_equal "<3", title.text
79
79
  =end
@@ -89,9 +89,9 @@ END
89
89
  entry = Atom::Entry.new
90
90
 
91
91
  entry.title = "<3"
92
- assert_raises(RuntimeError) { entry.title["type"] = "xhtml" }
93
-
94
- assert_raises(RuntimeError) do
92
+ assert_raises(Atom::ParseError) { entry.title["type"] = "xhtml" }
93
+
94
+ assert_raises(Atom::ParseError) do
95
95
  entry.title["type"] = "application/xhtml+xml"
96
96
  end
97
97
 
@@ -132,17 +132,30 @@ END
132
132
 
133
133
  assert_raises(ArgumentError) { entry.authors << "test" }
134
134
  assert_raises(ArgumentError) { entry.authors << link }
135
-
135
+
136
136
  entry.links << link
137
137
 
138
138
  assert_equal 1, entry.links.length
139
139
  end
140
140
 
141
+ def test_nice_multiple
142
+ entry = Atom::Entry.new
143
+
144
+ entry.authors.new :name => 'Brendan Taylor', :email => 'fake@fake.com', :uri => 'http://necronomicorp.com/bct'
145
+ entry.authors.new :name => 'some jerk'
146
+
147
+ assert_equal 2, entry.authors.length
148
+
149
+ assert_equal 'Brendan Taylor', entry.authors.first.name
150
+ end
151
+
141
152
  require "date"
142
153
  def test_date_construct
154
+ entry = Atom::Entry.new
155
+
143
156
  today = Date.today
144
- time = Atom::Time.new today
157
+ entry.updated = today
145
158
 
146
- assert_match(/^#{today}T00:00:00/, time.to_s)
159
+ assert_match(/^#{today}T00:00:00/, entry.updated.to_s)
147
160
  end
148
161
  end
data/test/test_feed.rb CHANGED
@@ -129,50 +129,6 @@ END
129
129
  assert_raises(Atom::HTTPException) { feed.update! }
130
130
  end
131
131
 
132
- def test_conditional_get
133
- @s.mount_proc("/") do |req,res|
134
- assert_nil req["If-None-Match"]
135
- assert_nil req["If-Modified-Since"]
136
-
137
- res["Etag"] = '"xyzzy"'
138
- res["Last-Modified"] = 'Wed, 15 Nov 1995 04:58:08 GMT'
139
- res.content_type = "application/atom+xml"
140
- res.body = @test_feed
141
-
142
- @s.stop
143
- end
144
-
145
- feed = Atom::Feed.new "http://localhost:#{@port}/"
146
-
147
- assert_equal 0, feed.entries.length
148
- assert_equal nil, feed.etag
149
- assert_equal nil, feed.last_modified
150
-
151
- one_shot
152
-
153
- feed.update!
154
-
155
- assert_equal 1, feed.entries.length
156
- assert_equal '"xyzzy"', feed.etag
157
- assert_equal 'Wed, 15 Nov 1995 04:58:08 GMT', feed.last_modified
158
-
159
- @s.mount_proc("/") do |req,res|
160
- assert_equal '"xyzzy"', req["If-None-Match"]
161
- assert_equal 'Wed, 15 Nov 1995 04:58:08 GMT', req["If-Modified-Since"]
162
-
163
- res.status = 304
164
- res.content_type = "application/atom+xml"
165
- res.body = @test_feed
166
-
167
- @s.stop
168
- end
169
-
170
- one_shot
171
- feed.update!
172
-
173
- assert_equal 1, feed.entries.length
174
- end
175
-
176
132
  # prepares the server for a single request
177
133
  def one_shot; Thread.new { @s.start }; end
178
134
  end
data/test/test_general.rb CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  require "test/unit"
4
4
 
5
- require "atom/yaml"
6
- require "atom/xml"
7
-
8
5
  require "atom/feed"
9
6
 
10
7
  class AtomTest < Test::Unit::TestCase
@@ -46,43 +43,6 @@ class AtomTest < Test::Unit::TestCase
46
43
  assert_has_category(xml, "tags")
47
44
  end
48
45
 
49
- def test_devour_yaml
50
- time = Time.parse "2007-01-18T12:37:46Z"
51
-
52
- yaml = <<END
53
- title: testing YAML
54
- draft: yes
55
-
56
- authors:
57
- - name: Mr. Safe
58
- uri: http://example.com/
59
-
60
- links:
61
- - href: http://atomenabled.org/
62
-
63
- content: not much here
64
-
65
- updated: #{time.iso8601}
66
- END
67
-
68
- entry = Atom::Entry.from_yaml(yaml)
69
-
70
- assert_equal("testing YAML", entry.title.to_s)
71
-
72
- assert entry.draft
73
-
74
- assert_equal(1, entry.authors.length)
75
- assert_equal("Mr. Safe", entry.authors.first.name)
76
- assert_equal("http://example.com/", entry.authors.first.uri)
77
-
78
- assert_equal(1, entry.links.length)
79
- assert_equal("http://atomenabled.org/", entry.links.first["href"])
80
-
81
- assert_equal("not much here", entry.content.to_s)
82
-
83
- assert_equal(time, entry.updated)
84
- end
85
-
86
46
  def assert_has_category xml, term
87
47
  assert_not_nil(REXML::XPath.match(xml, "/entry/category[@term = #{term}]"))
88
48
  end
data/test/test_http.rb CHANGED
@@ -254,6 +254,24 @@ class AtomHTTPTest < Test::Unit::TestCase
254
254
  assert_authenticates
255
255
  end
256
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
+
257
275
  def test_https
258
276
  require 'webrick/https'
259
277
 
@@ -5,15 +5,21 @@ require "atom/service"
5
5
  class FakeHTTP
6
6
  Response = Struct.new(:body, :code, :content_type)
7
7
 
8
- def initialize table, mime_type
8
+ def initialize table
9
9
  @table = table
10
- @mime_type = mime_type
11
10
  end
12
- def get url
11
+
12
+ def get url, headers = {}
13
13
  res = Response.new
14
- res.body = @table[url.to_s]
14
+
15
+ data = @table[url.to_s]
16
+
17
+ res.body = data[1]
15
18
  res.code = 200.to_s
16
- res.content_type = @mime_type
19
+ res.content_type = data[0]
20
+
21
+ def res.validate_content_type valid; valid.member? content_type; end
22
+
17
23
  res
18
24
  end
19
25
  end
@@ -35,30 +41,24 @@ class AtomProtocolTest < Test::Unit::TestCase
35
41
  </workspace>
36
42
  </service>
37
43
  END
38
-
39
- service = Atom::Service.new
40
- service.parse doc
44
+
45
+ service = Atom::Service.parse doc
41
46
 
42
47
  ws = service.workspaces.first
43
- assert_equal "My Blog", ws.title.to_s
48
+ assert_equal "My Blog", ws.title.to_s
44
49
 
45
50
  coll = ws.collections.first
46
- assert_equal URI.parse("http://example.org/myblog/entries"), coll.uri
51
+ assert_equal "http://example.org/myblog/entries", coll.href
47
52
  assert_equal "Entries", coll.title.to_s
48
53
  assert_equal ["application/atom+xml;type=entry"], coll.accepts
49
54
 
50
55
  coll = ws.collections.last
51
- assert_equal URI.parse("http://example.org/myblog/fotes"), coll.uri
56
+ assert_equal "http://example.org/myblog/fotes", coll.href
52
57
  assert_equal "Photos", coll.title.to_s
53
58
  assert_equal ["image/*"], coll.accepts
54
59
 
55
60
  http = service.instance_variable_get(:@http)
56
61
  assert_instance_of Atom::HTTP, http
57
-
58
- # collections should inherit the service's HTTP object
59
- assert_equal http, coll.instance_variable_get(:@http)
60
-
61
- # XXX write a test for relative hrefs
62
62
  end
63
63
 
64
64
  def test_write_introspection
@@ -83,10 +83,10 @@ END
83
83
 
84
84
  assert_equal "http://www.w3.org/2007/app", doc.root.namespace
85
85
 
86
- ws = REXML::XPath.first( doc.root,
87
- "/app:service/app:workspace",
86
+ ws = REXML::XPath.first( doc.root,
87
+ "/app:service/app:workspace",
88
88
  nses )
89
-
89
+
90
90
  title = REXML::XPath.first( ws, "./atom:title", nses)
91
91
 
92
92
  assert_equal "Workspace 1", title.text
@@ -122,9 +122,47 @@ END
122
122
  assert_instance_of Atom::HTTP, collection.instance_variable_get("@http")
123
123
  end
124
124
 
125
- def test_collection_properly_inherits_feed
126
- collection = Atom::Collection.new("http://necronomicorp.com/testatom?atom")
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
127
163
 
128
- assert_equal [], collection.links
164
+ assert_raises Atom::AutodiscoveryFailure do
165
+ Atom::Service.discover 'http://example.org/t', http
166
+ end
129
167
  end
130
168
  end
data/test/test_xml.rb CHANGED
@@ -1,18 +1,25 @@
1
+ $:.unshift 'lib/', File.dirname(__FILE__) + '/../lib'
1
2
  require "test/unit"
2
-
3
- # for entry.edit_url
4
3
  require "atom/service"
5
4
 
6
5
  class AtomTest < Test::Unit::TestCase
7
6
  def test_text_type_text
8
7
  entry = get_entry
9
8
 
10
- entry.title = "Atom-drunk pirates run amok!"
9
+ entry.title = "Let's talk about <html>"
11
10
  assert_equal("text", entry.title["type"])
12
11
 
13
- xml = get_elements entry
12
+ assert_match('&lt;', entry.title.xml.to_s)
13
+
14
+ xml = entry.to_xml
15
+
16
+ b = Atom::Entry.parse(xml).to_s
14
17
 
15
- assert_equal("Atom-drunk pirates run amok!", xml.elements["/entry/title"].text)
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)
16
23
  end
17
24
 
18
25
  def test_text_type_html
@@ -23,8 +30,10 @@ class AtomTest < Test::Unit::TestCase
23
30
 
24
31
  xml = get_elements entry
25
32
 
26
- assert_equal("Atom-drunk pirates<br>run amok!", xml.elements["/entry/title"].text)
27
- assert_equal("html", xml.elements["/entry/title"].attributes["type"])
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)
28
37
  end
29
38
 
30
39
  def test_text_type_xhtml
@@ -35,10 +44,10 @@ class AtomTest < Test::Unit::TestCase
35
44
 
36
45
  xml = get_elements entry
37
46
 
38
- base_check xml
47
+ assert_equal(XHTML::NS, xml.elements["title/div"].namespace)
48
+ assert_equal("run amok", xml.elements["title/div/em"].text)
39
49
 
40
- assert_equal(XHTML::NS, xml.elements["/entry/title/div"].namespace)
41
- assert_equal("run amok", xml.elements["/entry/title/div/em"].text)
50
+ assert_match('<em>', entry.to_s)
42
51
  end
43
52
 
44
53
  def test_html_text_with_entities
@@ -59,9 +68,9 @@ class AtomTest < Test::Unit::TestCase
59
68
 
60
69
  xml = get_elements entry
61
70
 
62
- assert_equal("http://necronomicorp.com/blog/", xml.elements["/entry/author/uri"].text)
63
- assert_equal("Brendan Taylor", xml.elements["/entry/author/name"].text)
64
- assert_nil(xml.elements["/entry/author/email"])
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"])
65
74
  end
66
75
 
67
76
  def test_tags
@@ -81,15 +90,36 @@ class AtomTest < Test::Unit::TestCase
81
90
 
82
91
  assert entry.updated.is_a?(Time)
83
92
 
84
- xml = get_elements entry
93
+ xml = entry.to_xml
94
+
95
+ b = Atom::Entry.parse(xml).to_s
96
+
97
+ base_check xml
85
98
 
86
- 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")
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")
87
100
 
88
101
  entry.updated!
89
102
 
90
103
  assert((Time.parse("1970-01-01") < entry.updated), "<updated/> is not updated")
91
104
  end
92
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
+
93
123
  def test_out_of_line
94
124
  entry = get_entry
95
125
 
@@ -99,25 +129,27 @@ class AtomTest < Test::Unit::TestCase
99
129
 
100
130
  xml = get_elements(entry)
101
131
 
102
- assert_nil(xml.elements["/entry/content"].text)
103
- assert_equal("http://example.org/test.png", xml.elements["/entry/content"].attributes["src"])
104
- assert_equal("image/png", xml.elements["/entry/content"].attributes["type"])
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"])
105
135
  end
106
136
 
107
137
  def test_extensions
108
138
  entry = get_entry
109
139
 
110
- assert(entry.extensions.children.empty?)
140
+ assert(entry.extensions.empty?)
111
141
 
112
142
  element = REXML::Element.new("test")
113
143
  element.add_namespace "http://purl.org/"
114
144
 
115
145
  entry.extensions << element
116
146
 
147
+ assert entry.extensions.member?(element)
148
+
117
149
  xml = get_elements entry
118
150
 
119
- assert_equal(REXML::Element, xml.elements["/entry/test"].class)
120
- assert_equal("http://purl.org/", xml.elements["/entry/test"].namespace)
151
+ assert_equal(REXML::Element, xml.elements["test"].class)
152
+ assert_equal("http://purl.org/", xml.elements["test"].namespace)
121
153
  end
122
154
 
123
155
  def test_roundtrip_extension
@@ -131,15 +163,15 @@ class AtomTest < Test::Unit::TestCase
131
163
 
132
164
  assert !entry.draft
133
165
 
134
- assert_nil get_elements(entry).elements["/entry/control"]
166
+ assert_nil get_elements(entry).elements["control"]
135
167
 
136
168
  entry.draft = true
137
169
 
138
170
  xml = get_elements entry
139
171
 
140
- assert_equal Atom::PP_NS, xml.elements["/entry/control"].namespace
141
- assert_equal Atom::PP_NS, xml.elements["/entry/control/draft"].namespace
142
- assert_equal "yes", xml.elements["/entry/control/draft"].text
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
143
175
 
144
176
  entry2 = Atom::Entry.parse xml
145
177
 
@@ -260,7 +292,7 @@ END
260
292
  assert_equal("tag:example.org,2003:3", feed.id)
261
293
 
262
294
  assert_equal([], feed.authors)
263
-
295
+
264
296
  alt = feed.links.find { |l| l["rel"] == "alternate" }
265
297
  assert_equal("alternate", alt["rel"])
266
298
  assert_equal("text/html", alt["type"])
@@ -309,19 +341,6 @@ END
309
341
  def test_parse_outofline_content
310
342
  xml = <<END
311
343
  <entry xmlns="http://www.w3.org/2005/Atom">
312
- <summary src="http://necronomicorp.com/nil">
313
- Summary doesn't have src.
314
- </summary>
315
- </entry>
316
- END
317
-
318
- entry = Atom::Entry.parse xml
319
-
320
- assert_raises(RuntimeError) { entry.summary["src"] }
321
- assert_equal "Summary doesn't have src.", entry.summary.to_s.strip
322
-
323
- xml = <<END
324
- <entry xmlns="http://www.w3.org/2005/Atom">
325
344
  <content src="http://necronomicorp.com/nil">
326
345
  src means empty content.
327
346
  </content>
@@ -356,6 +375,14 @@ END
356
375
  assert_equal("http://www.tbray.org/ongoing/When/200x/2006/10/11/", entry.base)
357
376
  end
358
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
+
359
386
  def test_edit_url
360
387
  doc = <<END
361
388
  <entry xmlns="http://www.w3.org/2005/Atom"><link rel="edit"/></entry>
@@ -381,6 +408,9 @@ END
381
408
  entry = Atom::Entry.parse(doc)
382
409
 
383
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
384
414
  end
385
415
 
386
416
  def assert_has_category xml, term
@@ -388,7 +418,7 @@ END
388
418
  end
389
419
 
390
420
  def assert_has_content_type xml, type
391
- assert_equal(type, xml.elements["/entry/content"].attributes["type"])
421
+ assert_equal(type, xml.elements["content"].attributes["type"])
392
422
  end
393
423
 
394
424
  def get_entry
@@ -399,7 +429,9 @@ END
399
429
  def get_elements entry
400
430
  xml = entry.to_xml
401
431
 
402
- assert_equal(entry.to_s, Atom::Entry.parse(xml).to_s)
432
+ b = Atom::Entry.parse(xml)
433
+
434
+ assert_equal(xml.to_s, b.to_s)
403
435
 
404
436
  base_check xml
405
437