atom-tools 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/COPYING +18 -0
  2. data/README +103 -0
  3. data/Rakefile +77 -0
  4. data/bin/atom-client.rb +246 -0
  5. data/bin/atom-server.rb~ +71 -0
  6. data/doc/classes/Atom/App.html +217 -0
  7. data/doc/classes/Atom/Author.html +130 -0
  8. data/doc/classes/Atom/Category.html +128 -0
  9. data/doc/classes/Atom/Collection.html +322 -0
  10. data/doc/classes/Atom/Content.html +129 -0
  11. data/doc/classes/Atom/Contributor.html +119 -0
  12. data/doc/classes/Atom/Element.html +325 -0
  13. data/doc/classes/Atom/Entry.html +365 -0
  14. data/doc/classes/Atom/Feed.html +585 -0
  15. data/doc/classes/Atom/HTTP.html +374 -0
  16. data/doc/classes/Atom/Link.html +137 -0
  17. data/doc/classes/Atom/Text.html +229 -0
  18. data/doc/classes/XHTML.html +118 -0
  19. data/doc/created.rid +1 -0
  20. data/doc/files/README.html +213 -0
  21. data/doc/files/lib/atom/app_rb.html +110 -0
  22. data/doc/files/lib/atom/collection_rb.html +110 -0
  23. data/doc/files/lib/atom/element_rb.html +109 -0
  24. data/doc/files/lib/atom/entry_rb.html +111 -0
  25. data/doc/files/lib/atom/feed_rb.html +112 -0
  26. data/doc/files/lib/atom/http_rb.html +109 -0
  27. data/doc/files/lib/atom/text_rb.html +108 -0
  28. data/doc/files/lib/atom/xml_rb.html +110 -0
  29. data/doc/files/lib/atom/yaml_rb.html +109 -0
  30. data/doc/fr_class_index.html +39 -0
  31. data/doc/fr_file_index.html +36 -0
  32. data/doc/fr_method_index.html +62 -0
  33. data/doc/index.html +24 -0
  34. data/doc/rdoc-style.css +208 -0
  35. data/lib/atom/app.rb +87 -0
  36. data/lib/atom/collection.rb +75 -0
  37. data/lib/atom/element.rb +277 -0
  38. data/lib/atom/entry.rb +135 -0
  39. data/lib/atom/feed.rb +229 -0
  40. data/lib/atom/http.rb +132 -0
  41. data/lib/atom/text.rb +163 -0
  42. data/lib/atom/xml.rb +200 -0
  43. data/lib/atom/yaml.rb +101 -0
  44. data/setup.rb +1585 -0
  45. data/test/conformance/order.rb +117 -0
  46. data/test/conformance/title.rb +108 -0
  47. data/test/conformance/updated.rb +33 -0
  48. data/test/conformance/xhtmlcontentdiv.rb +18 -0
  49. data/test/conformance/xmlnamespace.rb +54 -0
  50. data/test/runtests.rb +14 -0
  51. data/test/test_constructs.rb +91 -0
  52. data/test/test_feed.rb +128 -0
  53. data/test/test_general.rb +99 -0
  54. data/test/test_http.rb +86 -0
  55. data/test/test_protocol.rb +69 -0
  56. data/test/test_xml.rb +353 -0
  57. metadata +107 -0
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require "test/unit"
4
+
5
+ require "atom/yaml"
6
+ require "atom/xml"
7
+
8
+ require "atom/feed"
9
+
10
+ class AtomTest < Test::Unit::TestCase
11
+ def test_feed_duplicate_id
12
+ feed = Atom::Feed.new
13
+
14
+ entry1 = get_entry
15
+ entry1.id = "http://example.org/test"
16
+ entry1.content = "an original entry"
17
+ entry1.updated!
18
+
19
+ feed << entry1
20
+
21
+ assert_equal(1, feed.entries.length)
22
+ assert_equal("an original entry", feed.entries.first.content.to_s)
23
+
24
+ feed << entry1.dup
25
+
26
+ assert_equal(1, feed.entries.length)
27
+ assert_equal("an original entry", feed.entries.first.content.to_s)
28
+
29
+ entry2 = entry1.dup
30
+ entry2.content = "a changed entry"
31
+ entry2.updated!
32
+
33
+ feed << entry2
34
+
35
+ assert_equal(1, feed.entries.length)
36
+ assert_equal("a changed entry", feed.entries.last.content.to_s)
37
+ end
38
+
39
+ def test_tags
40
+ entry = get_entry
41
+ entry.tag_with "test tags"
42
+
43
+ xml = get_elements entry
44
+
45
+ assert_has_category(xml, "test")
46
+ assert_has_category(xml, "tags")
47
+ end
48
+
49
+ def test_snarf_yaml
50
+ yaml = """title: testing YAML
51
+ authors:
52
+ - name: Mr. Safe
53
+ uri: http://example.com/
54
+ links:
55
+ - href: http://atomenabled.org/
56
+ content: not much here\
57
+ """
58
+
59
+ entry = Atom::Entry.from_yaml(yaml)
60
+
61
+ assert_equal("testing YAML", entry.title.to_s)
62
+
63
+ assert_equal(1, entry.authors.length)
64
+ assert_equal("Mr. Safe", entry.authors.first.name)
65
+ assert_equal("http://example.com/", entry.authors.first.uri)
66
+
67
+ assert_equal(1, entry.links.length)
68
+ assert_equal("http://atomenabled.org/", entry.links.first["href"])
69
+
70
+ assert_equal("not much here", entry.content.to_s)
71
+ end
72
+
73
+ def assert_has_category xml, term
74
+ assert_not_nil(REXML::XPath.match(xml, "/entry/category[@term = #{term}]"))
75
+ end
76
+
77
+ def assert_has_content_type xml, type
78
+ assert_equal(type, xml.elements["/entry/content"].attributes["type"])
79
+ end
80
+
81
+ def get_entry
82
+ Atom::Entry.new
83
+ end
84
+
85
+ def get_elements entry
86
+ xml = entry.to_xml
87
+
88
+ assert_equal(entry.to_s, Atom::Entry.parse(xml).to_s)
89
+
90
+ base_check xml
91
+
92
+ xml
93
+ end
94
+
95
+ def base_check xml
96
+ assert_equal("entry", xml.root.name)
97
+ assert_equal("http://www.w3.org/2005/Atom", xml.root.namespace)
98
+ end
99
+ end
data/test/test_http.rb ADDED
@@ -0,0 +1,86 @@
1
+ require "atom/http"
2
+ require "webrick"
3
+
4
+ class AtomProtocolTest < Test::Unit::TestCase
5
+ def setup
6
+ @http = Atom::HTTP.new
7
+ @port = rand(1024) + 1024
8
+ @s = WEBrick::HTTPServer.new :Port => @port,
9
+ :Logger => WEBrick::Log.new($stderr, WEBrick::Log::FATAL),
10
+ :AccessLog => []
11
+ end
12
+
13
+ def test_parse_wwwauth
14
+ header = 'Basic realm="SokEvo"'
15
+
16
+ # parse_wwwauth is a private method
17
+ auth_type, auth_params = @http.send :parse_wwwauth, header
18
+
19
+ assert_equal "Basic", auth_type
20
+ assert_equal "SokEvo", auth_params["realm"]
21
+ end
22
+
23
+ def test_GET
24
+ @s.mount_proc("/") do |req,res|
25
+ assert_equal("/", req.path)
26
+
27
+ res.content_type = "text/plain"
28
+ res.body = "just junk"
29
+
30
+ @s.stop
31
+ end
32
+
33
+ one_shot
34
+
35
+ res = get_root
36
+
37
+ assert_equal("200", res.code)
38
+ assert_equal("text/plain", res.content_type)
39
+ assert_equal("just junk", res.body)
40
+ end
41
+
42
+ def test_GET_headers
43
+ @s.mount_proc("/") do |req,res|
44
+ assert_equal("tester agent", req["User-Agent"])
45
+
46
+ @s.stop
47
+ end
48
+
49
+ one_shot
50
+
51
+ res = get_root("User-Agent" => "tester agent")
52
+
53
+ assert_equal("200", res.code)
54
+ end
55
+
56
+ def test_basic_auth
57
+ @s.mount_proc("/") do |req,res|
58
+ WEBrick::HTTPAuth.basic_auth(req, res, "test authentication") do |u,p|
59
+ u == "test" and p == "pass"
60
+ end
61
+
62
+ res.body = "sooper-secret!"
63
+ @s.stop
64
+ end
65
+
66
+ one_shot
67
+
68
+ assert_raises(Atom::Unauthorized) { get_root }
69
+
70
+ @http.when_auth do |abs_url,realm|
71
+ assert_equal "http://localhost:#{@port}/", abs_url
72
+ assert_equal "test authentication", realm
73
+
74
+ ["test", "pass"]
75
+ end
76
+
77
+ one_shot
78
+
79
+ res = get_root
80
+ assert_equal("200", res.code)
81
+ assert_equal("sooper-secret!", res.body)
82
+ end
83
+
84
+ def get_root(*args); @http.get("http://localhost:#{@port}/", *args); end
85
+ def one_shot; Thread.new { @s.start }; end
86
+ end
@@ -0,0 +1,69 @@
1
+ require "test/unit"
2
+
3
+ require "atom/app"
4
+
5
+ class FakeHTTP
6
+ Response = Struct.new(:body, :code, :content_type)
7
+
8
+ def initialize table, mime_type
9
+ @table = table
10
+ @mime_type = mime_type
11
+ end
12
+ def get url
13
+ res = Response.new
14
+ res.body = @table[url.to_s]
15
+ res.code = 200.to_s
16
+ res.content_type = @mime_type
17
+ res
18
+ end
19
+ end
20
+
21
+ class AtomProtocolTest < Test::Unit::TestCase
22
+ def test_introspection
23
+
24
+ service = <<END
25
+ <service xmlns="http://purl.org/atom/app#"
26
+ xmlns:atom="http://www.w3.org/2005/Atom">
27
+ <workspace>
28
+ <atom:title>My Blog</atom:title>
29
+ <collection href="http://example.org/myblog/entries">
30
+ <atom:title>Entries</atom:title>
31
+ </collection>
32
+ <collection href="http://example.org/myblog/fotes">
33
+ <atom:title>Photos</atom:title>
34
+ <accept>image/*</accept>
35
+ </collection>
36
+ </workspace>
37
+ </service>
38
+ END
39
+
40
+ http = FakeHTTP.new({ "http://example.com/service.xml" => service }, "application/atomserv+xml")
41
+
42
+
43
+ server = Atom::App.new "http://example.com/service.xml", http
44
+
45
+ coll = server.collections.first
46
+ assert_equal(URI.parse("http://example.org/myblog/entries"), coll.uri)
47
+ assert_equal("Entries", coll.title.to_s)
48
+ assert_equal("entry", coll.accepts)
49
+
50
+ coll = server.collections.last
51
+ assert_equal(URI.parse("http://example.org/myblog/fotes"), coll.uri)
52
+ assert_equal("Photos", coll.title.to_s)
53
+ assert_equal("image/*", coll.accepts)
54
+
55
+ # XXX write a test for relative hrefs
56
+ end
57
+
58
+ def test_dont_specify_http_object
59
+ collection = Atom::Collection.new("http://necronomicorp.com/testatom?atom")
60
+
61
+ assert_instance_of Atom::HTTP, collection.instance_variable_get("@http")
62
+ end
63
+
64
+ def test_collection_properly_inherits_feed
65
+ collection = Atom::Collection.new("http://necronomicorp.com/testatom?atom")
66
+
67
+ assert_equal [], collection.links
68
+ end
69
+ end
data/test/test_xml.rb ADDED
@@ -0,0 +1,353 @@
1
+ require "test/unit"
2
+
3
+ # for entry.edit_url
4
+ require "atom/app"
5
+
6
+ class AtomTest < Test::Unit::TestCase
7
+ def test_text_type_text
8
+ entry = get_entry
9
+
10
+ entry.title = "Atom-drunk pirates run amok!"
11
+ assert_equal("text", entry.title["type"])
12
+
13
+ xml = get_elements entry
14
+
15
+ assert_equal("Atom-drunk pirates run amok!", xml.elements["/entry/title"].text)
16
+ end
17
+
18
+ def test_text_type_html
19
+ entry = get_entry
20
+
21
+ entry.title = "Atom-drunk pirates<br>run amok!"
22
+ entry.title["type"] = "html"
23
+
24
+ xml = get_elements entry
25
+
26
+ assert_equal("Atom-drunk pirates<br>run amok!", xml.elements["/entry/title"].text)
27
+ assert_equal("html", xml.elements["/entry/title"].attributes["type"])
28
+ end
29
+
30
+ def test_text_type_xhtml
31
+ entry = get_entry
32
+
33
+ entry.title = "Atom-drunk pirates <em>run amok</em>!"
34
+ entry.title["type"] = "xhtml"
35
+
36
+ xml = get_elements entry
37
+
38
+ base_check xml
39
+
40
+ assert_equal(XHTML::NS, xml.elements["/entry/title/div"].namespace)
41
+ assert_equal("run amok", xml.elements["/entry/title/div/em"].text)
42
+ end
43
+
44
+ def test_author
45
+ entry = get_entry
46
+ a = entry.authors.new
47
+
48
+ a.name= "Brendan Taylor"
49
+ a.uri = "http://necronomicorp.com/blog/"
50
+
51
+ xml = get_elements entry
52
+
53
+ assert_equal("http://necronomicorp.com/blog/", xml.elements["/entry/author/uri"].text)
54
+ assert_equal("Brendan Taylor", xml.elements["/entry/author/name"].text)
55
+ assert_nil(xml.elements["/entry/author/email"])
56
+ end
57
+
58
+ def test_tags
59
+ entry = get_entry
60
+ entry.tag_with "test tags"
61
+
62
+ xml = get_elements entry
63
+
64
+ assert_has_category(xml, "test")
65
+ assert_has_category(xml, "tags")
66
+ end
67
+
68
+ def test_updated
69
+ entry = get_entry
70
+ entry.updated = "1970-01-01"
71
+ entry.content = "blah"
72
+
73
+ assert_instance_of(Time, entry.updated)
74
+
75
+ xml = get_elements entry
76
+
77
+ 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")
78
+
79
+ entry.updated!
80
+
81
+ assert((Time.parse("1970-01-01") < entry.updated), "<updated/> is not updated")
82
+ end
83
+
84
+ def test_out_of_line
85
+ entry = get_entry
86
+
87
+ entry.content = "this shouldn't appear"
88
+ entry.content["src"] = 'http://example.org/test.png'
89
+ entry.content["type"] = "image/png"
90
+
91
+ xml = get_elements(entry)
92
+
93
+ assert_nil(xml.elements["/entry/content"].text)
94
+ assert_equal("http://example.org/test.png", xml.elements["/entry/content"].attributes["src"])
95
+ assert_equal("image/png", xml.elements["/entry/content"].attributes["type"])
96
+ end
97
+
98
+ def test_extensions
99
+ entry = get_entry
100
+
101
+ assert(entry.extensions.children.empty?)
102
+
103
+ element = REXML::Element.new("test")
104
+ element.add_namespace "http://purl.org/"
105
+
106
+ entry.extensions << element
107
+
108
+ xml = get_elements entry
109
+
110
+ assert_equal(REXML::Element, xml.elements["/entry/test"].class)
111
+ assert_equal("http://purl.org/", xml.elements["/entry/test"].namespace)
112
+ end
113
+
114
+ def test_extensive_enty_parsing
115
+ str = '<entry xmlns="http://www.w3.org/2005/Atom">
116
+ <title>Atom draft-07 snapshot</title>
117
+ <link rel="alternate" type="text/html"
118
+ href="http://example.org/2005/04/02/atom"/>
119
+ <link rel="enclosure" type="audio/mpeg" length="1337"
120
+ href="http://example.org/audio/ph34r_my_podcast.mp3"/>
121
+ <id>tag:example.org,2003:3.2397</id>
122
+ <updated>2005-07-31T12:29:29Z</updated>
123
+ <published>2003-12-13T08:29:29-04:00</published>
124
+ <author>
125
+ <name>Mark Pilgrim</name>
126
+ <uri>http://example.org/</uri>
127
+ <email>f8dy@example.com</email>
128
+ </author>
129
+ <contributor>
130
+ <name>Sam Ruby</name>
131
+ </contributor>
132
+ <contributor>
133
+ <name>Joe Gregorio</name>
134
+ </contributor>
135
+ <content type="xhtml" xml:lang="en"
136
+ xml:base="http://diveintomark.org/">
137
+ <div xmlns="http://www.w3.org/1999/xhtml">
138
+ <p><i>[Update: The Atom draft is finished.]</i></p>
139
+ </div>
140
+ </content>
141
+ </entry>'
142
+
143
+ entry = Atom::Entry.parse(str)
144
+
145
+ assert_equal("Atom draft-07 snapshot", entry.title.to_s)
146
+ assert_equal("tag:example.org,2003:3.2397", entry.id)
147
+
148
+ assert_equal(Time.parse("2005-07-31T12:29:29Z"), entry.updated)
149
+ assert_equal(Time.parse("2003-12-13T08:29:29-04:00"), entry.published)
150
+
151
+ assert_equal(2, entry.links.length)
152
+ assert_equal("alternate", entry.links.first["rel"])
153
+ assert_equal("text/html", entry.links.first["type"])
154
+ assert_equal("http://example.org/2005/04/02/atom", entry.links.first["href"])
155
+
156
+ assert_equal("enclosure", entry.links.last["rel"])
157
+ assert_equal("audio/mpeg", entry.links.last["type"])
158
+ assert_equal("1337", entry.links.last["length"])
159
+ assert_equal("http://example.org/audio/ph34r_my_podcast.mp3", entry.links.last["href"])
160
+
161
+ assert_equal(1, entry.authors.length)
162
+ assert_equal("Mark Pilgrim", entry.authors.first.name)
163
+ assert_equal("http://example.org/", entry.authors.first.uri)
164
+ assert_equal("f8dy@example.com", entry.authors.first.email)
165
+
166
+ assert_equal(2, entry.contributors.length)
167
+ assert_equal("Sam Ruby", entry.contributors.first.name)
168
+ assert_equal("Joe Gregorio", entry.contributors.last.name)
169
+
170
+ assert_equal("xhtml", entry.content["type"])
171
+
172
+ assert_match("<p><i>[Update: The Atom draft is finished.]</i></p>",
173
+ entry.content.to_s)
174
+
175
+ assert_equal("http://diveintomark.org/", entry.content.base)
176
+ # XXX unimplemented
177
+ # assert_equal("en", entry.content.lang)
178
+ end
179
+
180
+ def test_extensive_feed_parsing
181
+ feed = <<END
182
+ <?xml version="1.0" encoding="utf-8"?>
183
+ <feed xmlns="http://www.w3.org/2005/Atom">
184
+ <title type="text">dive into mark</title>
185
+ <subtitle type="html">
186
+ A &lt;em&gt;lot&lt;/em&gt; of effort
187
+ went into making this effortless
188
+ </subtitle>
189
+ <updated>2005-07-31T12:29:29Z</updated>
190
+ <id>tag:example.org,2003:3</id>
191
+ <link rel="alternate" type="text/html"
192
+ hreflang="en" href="http://example.org/"/>
193
+ <link rel="self" type="application/atom+xml"
194
+ href="http://example.org/feed.atom"/>
195
+ <rights>Copyright (c) 2003, Mark Pilgrim</rights>
196
+ <generator uri="http://www.example.com/" version="1.0">
197
+ Example Toolkit
198
+ </generator>
199
+ <entry>
200
+ <title>Atom draft-07 snapshot</title>
201
+ <author>
202
+ <name>Mark Pilgrim</name>
203
+ <uri>http://example.org/</uri>
204
+ <email>f8dy@example.com</email>
205
+ </author>
206
+ <link rel="alternate" type="text/html"
207
+ href="http://example.org/2005/04/02/atom"/>
208
+ <id>tag:example.org,2003:3.2397</id>
209
+ <updated>2005-07-31T12:29:29Z</updated>
210
+ </entry>
211
+ </feed>
212
+ END
213
+
214
+ feed = Atom::Feed.parse(feed)
215
+
216
+ assert_equal("", feed.base)
217
+
218
+ assert_equal("text", feed.title["type"])
219
+ assert_equal("dive into mark", feed.title.to_s)
220
+
221
+ assert_equal("html", feed.subtitle["type"])
222
+ assert_equal("\n A <em>lot</em> of effort\n went into making this effortless\n ", feed.subtitle.to_s)
223
+
224
+ assert_equal(Time.parse("2005-07-31T12:29:29Z"), feed.updated)
225
+ assert_equal("tag:example.org,2003:3", feed.id)
226
+
227
+ assert_equal([], feed.authors)
228
+
229
+ alt = feed.links.find { |l| l["rel"] == "alternate" }
230
+ assert_equal("alternate", alt["rel"])
231
+ assert_equal("text/html", alt["type"])
232
+ assert_equal("en", alt["hreflang"])
233
+ assert_equal("http://example.org/", alt["href"])
234
+
235
+ assert_equal("text", feed.rights["type"])
236
+ assert_equal("Copyright (c) 2003, Mark Pilgrim", feed.rights.to_s)
237
+
238
+ assert_equal("\n Example Toolkit\n ", feed.generator)
239
+ # XXX unimplemented
240
+ # assert_equal("http://www.example.com/", feed.generator["uri"])
241
+ # assert_equal("1.0", feed.generator["version"])
242
+
243
+ assert_equal(1, feed.entries.length)
244
+ assert_equal "Atom draft-07 snapshot", feed.entries.first.title.to_s
245
+ end
246
+
247
+ def test_parse_html_content
248
+ xml = <<END
249
+ <entry xmlns="http://www.w3.org/2005/Atom">
250
+ <summary type="html">
251
+ &lt;p>...&amp;amp; as a result of this, I submit that &lt;var>pi&lt;/var> &amp;lt; 4
252
+ </summary>
253
+ </entry>
254
+ END
255
+
256
+ entry = Atom::Entry.parse(xml)
257
+
258
+ assert_equal "html", entry.summary["type"]
259
+ assert_equal "<p>...&amp; as a result of this, I submit that <var>pi</var> &lt; 4", entry.summary.html.strip
260
+ end
261
+
262
+ def test_parse_outofline_content
263
+ xml = <<END
264
+ <entry xmlns="http://www.w3.org/2005/Atom">
265
+ <summary src="http://necronomicorp.com/nil">
266
+ Summary doesn't have src.
267
+ </summary>
268
+ </entry>
269
+ END
270
+
271
+ entry = Atom::Entry.parse xml
272
+
273
+ assert_raises(RuntimeError) { entry.summary["src"] }
274
+ assert_equal "Summary doesn't have src.", entry.summary.to_s.strip
275
+
276
+ xml = <<END
277
+ <entry xmlns="http://www.w3.org/2005/Atom">
278
+ <content src="http://necronomicorp.com/nil">
279
+ src means empty content.
280
+ </content>
281
+ </entry>
282
+ END
283
+
284
+ entry = Atom::Entry.parse xml
285
+
286
+ assert_equal "http://necronomicorp.com/nil", entry.content["src"]
287
+ assert_equal "", entry.content.to_s
288
+ end
289
+
290
+ def test_relative_base
291
+ base_url = "http://www.tbray.org/ongoing/ongoing.atom"
292
+ doc = "<entry xmlns='http://www.w3.org/2005/Atom' xml:base='When/200x/2006/10/11/'/>"
293
+
294
+ entry = Atom::Entry.parse(doc, base_url)
295
+ assert_equal("http://www.tbray.org/ongoing/When/200x/2006/10/11/", entry.base)
296
+ end
297
+
298
+ def test_edit_url
299
+ doc = <<END
300
+ <entry xmlns="http://www.w3.org/2005/Atom"><link rel="edit"/></entry>
301
+ END
302
+ entry = Atom::Entry.parse(doc)
303
+
304
+ assert_nil(entry.edit_url)
305
+
306
+ doc = <<END
307
+ <entry xmlns="http://www.w3.org/2005/Atom"><link rel="edit"/></entry>
308
+ END
309
+
310
+ entry = Atom::Entry.parse(doc)
311
+
312
+ assert_nil(entry.edit_url)
313
+
314
+ doc = <<END
315
+ <entry xmlns="http://www.w3.org/2005/Atom">
316
+ <link rel="edit" href="http://necronomicorp.com/nil"/>
317
+ </entry>
318
+ END
319
+
320
+ entry = Atom::Entry.parse(doc)
321
+
322
+ assert_equal("http://necronomicorp.com/nil", entry.edit_url)
323
+ end
324
+
325
+
326
+ def assert_has_category xml, term
327
+ assert_not_nil(REXML::XPath.match(xml, "/entry/category[@term = #{term}]"))
328
+ end
329
+
330
+ def assert_has_content_type xml, type
331
+ assert_equal(type, xml.elements["/entry/content"].attributes["type"])
332
+ end
333
+
334
+ def get_entry
335
+ Atom::Entry.new
336
+ end
337
+
338
+ # round-trips it to make sure things stay the same
339
+ def get_elements entry
340
+ xml = entry.to_xml
341
+
342
+ assert_equal(entry.to_s, Atom::Entry.parse(xml).to_s)
343
+
344
+ base_check xml
345
+
346
+ xml
347
+ end
348
+
349
+ def base_check xml
350
+ assert_equal("entry", xml.root.name)
351
+ assert_equal("http://www.w3.org/2005/Atom", xml.root.namespace)
352
+ end
353
+ end