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,117 @@
1
+ require "test/unit"
2
+ require "atom/feed"
3
+
4
+ # http://www.intertwingly.net/wiki/pie/OrderConformanceTests
5
+
6
+ FEED = Atom::Feed.new("http://www.snellspace.com/public/ordertest.xml")
7
+ FEED.update!
8
+
9
+ class TestOrderConformance < Test::Unit::TestCase
10
+ def test_0
11
+ entry = FEED.entries[0]
12
+
13
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/1", entry.id
14
+ assert_equal "Simple order, nothing fancy", entry.title.to_s
15
+ assert_equal "Simple ordering, nothing fancy", entry.summary.to_s
16
+ assert_equal Time.parse("2006-01-26T09:20:01Z"), entry.updated
17
+
18
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
19
+ end
20
+
21
+ def test_1
22
+ entry = FEED.entries[1]
23
+
24
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/2", entry.id
25
+ assert_equal "Same as the first, only mixed up a bit", entry.title.to_s
26
+ assert_equal "Same as the first, only mixed up a bit", entry.summary.to_s
27
+ assert_equal Time.parse("2006-01-26T09:20:02Z"), entry.updated
28
+
29
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
30
+ end
31
+
32
+ # Multiple alt link elements, which does your reader show?
33
+ def test_2
34
+ entry = FEED.entries[2]
35
+
36
+ # both links should be available, but it's up to you to choose which one to use
37
+ assert_link_href(entry, "http://www.snellspace.com/public/alternate") { |l| l["rel"] == "alternate" and l["type"] == nil }
38
+
39
+ assert_link_href(entry, "http://www.snellspace.com/public/alternate2") { |l| l["rel"] == "alternate" and l["type"] == "text/plain" }
40
+ end
41
+
42
+ # Multiple link elements, does your feed reader show the "alternate" correctly? (also checks to see if the reader is paying attention to link rel values)
43
+ def test_3
44
+ entry = FEED.entries[3]
45
+
46
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
47
+
48
+ assert_link_href(entry, "http://www.snellspace.com/public/related") { |l| l["rel"] == "related" }
49
+
50
+ assert_link_href(entry, "http://www.snellspace.com/public/foo") { |l| l["rel"] == "urn:foo" }
51
+ end
52
+
53
+ # Entry with a source first.. does your feed reader show the right title, updated, and alt link?
54
+ def test_4
55
+ entry = FEED.entries[4]
56
+
57
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/5", entry.id
58
+ assert_equal "Entry with a source first", entry.title.to_s
59
+ assert_equal Time.parse("2006-01-26T09:20:05Z"), entry.updated
60
+
61
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
62
+ end
63
+
64
+ # Entry with a source first.. does your feed reader show the right title, updated, and alt link?
65
+ # ^-- quoted summary is a typo, source is last
66
+ def test_5
67
+ entry = FEED.entries[5]
68
+
69
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/6", entry.id
70
+ assert_equal "Entry with a source last", entry.title.to_s
71
+ assert_equal Time.parse("2006-01-26T09:20:06Z"), entry.updated
72
+
73
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
74
+ end
75
+
76
+ # Entry with a source in the middle.. does your feed reader show the right id, title, updated, and alt link?
77
+ def test_6
78
+ entry = FEED.entries[6]
79
+
80
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/7", entry.id
81
+ assert_equal "Entry with a source in the middle", entry.title.to_s
82
+ assert_equal Time.parse("2006-01-26T09:20:07Z"), entry.updated
83
+
84
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
85
+ end
86
+
87
+ # Atom elements in an extension element
88
+ def test_7
89
+ entry = FEED.entries[7]
90
+
91
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/8", entry.id
92
+ assert_equal "Atom elements in an extension element", entry.title.to_s
93
+ assert_equal Time.parse("2006-01-26T09:20:08Z"), entry.updated
94
+
95
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
96
+ end
97
+
98
+ # Atom elements in an extension element
99
+ def test_8
100
+ entry = FEED.entries[8]
101
+
102
+ assert_equal "tag:example.org,2006:atom/conformance/element_order/9", entry.id
103
+ assert_equal "Atom elements in an extension element", entry.title.to_s
104
+ assert_equal Time.parse("2006-01-26T09:20:09Z"), entry.updated
105
+
106
+ assert_alternate_href(entry, "http://www.snellspace.com/public/alternate")
107
+ end
108
+
109
+ def assert_link_href(entry, href, &block)
110
+ link = entry.links.find(&block)
111
+ assert_equal href, link["href"]
112
+ end
113
+
114
+ def assert_alternate_href(entry, href)
115
+ assert_link_href(entry, href) { |l| l["rel"] == "alternate" }
116
+ end
117
+ end
@@ -0,0 +1,108 @@
1
+ require "test/unit"
2
+ require "atom/feed"
3
+
4
+ # wiki page at <http://www.intertwingly.net/wiki/pie/TitleConformanceTests>
5
+
6
+ # http://atomtests.philringnalda.com/tests/item/title/html-cdata.atom
7
+ # http://atomtests.philringnalda.com/tests/item/title/html-entity.atom
8
+ # http://atomtests.philringnalda.com/tests/item/title/html-ncr.atom
9
+ # http://atomtests.philringnalda.com/tests/item/title/text-cdata.atom
10
+ # http://atomtests.philringnalda.com/tests/item/title/text-entity.atom
11
+ # http://atomtests.philringnalda.com/tests/item/title/text-ncr.atom
12
+ # http://atomtests.philringnalda.com/tests/item/title/xhtml-entity.atom
13
+ # http://atomtests.philringnalda.com/tests/item/title/xhtml-ncr.atom
14
+
15
+ # I make no attempt to normalize the XML from entry.title.to_s
16
+ # therefore, the direct equalities I do below are unwise.
17
+ # (eg. they *could* return &lt; or &#60; and still be perfectly correct)
18
+ #
19
+ # It shouldn't be a problem unless REXML changes what it encodes.
20
+ class TestTitleConformance < Test::Unit::TestCase
21
+ def test_html_cdata
22
+ url = "http://atomtests.philringnalda.com/tests/item/title/html-cdata.atom"
23
+
24
+ feed = Atom::Feed.new(url)
25
+ feed.update!
26
+
27
+ entry = feed.entries.first
28
+ assert_equal "html", entry.title["type"]
29
+ assert_equal "&lt;title>", entry.title.html
30
+ end
31
+
32
+ def test_html_entity
33
+ url = "http://atomtests.philringnalda.com/tests/item/title/html-entity.atom"
34
+
35
+ feed = Atom::Feed.new(url)
36
+ feed.update!
37
+
38
+ entry = feed.entries.first
39
+ assert_equal "html", entry.title["type"]
40
+ assert_equal "&lt;title>", entry.title.html
41
+ end
42
+
43
+ def test_html_ncr
44
+ url = "http://atomtests.philringnalda.com/tests/item/title/html-ncr.atom"
45
+
46
+ feed = Atom::Feed.new(url)
47
+ feed.update!
48
+
49
+ entry = feed.entries.first
50
+ assert_equal "html", entry.title["type"]
51
+ assert_equal "&lt;title>", entry.title.html
52
+ end
53
+
54
+ def test_text_cdata
55
+ url = "http://atomtests.philringnalda.com/tests/item/title/text-cdata.atom"
56
+
57
+ feed = Atom::Feed.new(url)
58
+ feed.update!
59
+
60
+ entry = feed.entries.first
61
+ assert_equal "text", entry.title["type"]
62
+ assert_equal "&lt;title&gt;", entry.title.html
63
+ end
64
+
65
+ def test_text_entity
66
+ url = "http://atomtests.philringnalda.com/tests/item/title/text-entity.atom"
67
+
68
+ feed = Atom::Feed.new(url)
69
+ feed.update!
70
+
71
+ entry = feed.entries.first
72
+ assert_equal "text", entry.title["type"]
73
+ assert_equal "&lt;title&gt;", entry.title.html
74
+ end
75
+
76
+ def test_text_ncr
77
+ url = "http://atomtests.philringnalda.com/tests/item/title/text-ncr.atom"
78
+
79
+ feed = Atom::Feed.new(url)
80
+ feed.update!
81
+
82
+ entry = feed.entries.first
83
+ assert_equal "text", entry.title["type"]
84
+ assert_equal "&lt;title&gt;", entry.title.html
85
+ end
86
+
87
+ def test_xhtml_entity
88
+ url = "http://atomtests.philringnalda.com/tests/item/title/xhtml-entity.atom"
89
+
90
+ feed = Atom::Feed.new(url)
91
+ feed.update!
92
+
93
+ entry = feed.entries.first
94
+ assert_equal "xhtml", entry.title["type"]
95
+ assert_equal "&lt;title>", entry.title.html
96
+ end
97
+
98
+ def test_xhtml_ncr
99
+ url = "http://atomtests.philringnalda.com/tests/item/title/xhtml-ncr.atom"
100
+
101
+ feed = Atom::Feed.new(url)
102
+ feed.update!
103
+
104
+ entry = feed.entries.first
105
+ assert_equal "xhtml", entry.title["type"]
106
+ assert_equal "&#60;title>", entry.title.html
107
+ end
108
+ end
@@ -0,0 +1,33 @@
1
+ require "test/unit"
2
+ require "atom/feed"
3
+
4
+ # wiki page at <http://www.intertwingly.net/wiki/pie/UpdatedConformanceTests>
5
+ # test feed at <http://intertwingly.net/testcase/updated.atom>
6
+
7
+ class TestUpdatedConformance < Test::Unit::TestCase
8
+ def test_it_all
9
+ feed = Atom::Feed.new "http://intertwingly.net/testcase/updated.atom"
10
+
11
+ assert_equal [], feed.entries
12
+
13
+ # initial filling
14
+ feed.update!
15
+ assert_equal "12 of 13 miner survive mine collapse", feed.entries.first.content.to_s.strip
16
+
17
+ # this is an insignificant change,
18
+ # (ie. atom:updated_1 == atom:updated_2),
19
+ # but that's for you to handle
20
+ feed.update!
21
+ assert_equal "12 of 13 miner<b>s</b> survive mine collapse", feed.entries.first.content.to_s.strip
22
+
23
+ # now we've got a significant change
24
+ feed.update!
25
+ assert_equal "12 of 13 miners <del>survive</del> <b>killed</b> in mine collapse", feed.entries.first.content.to_s.strip
26
+
27
+ # and now the feed is gone totally
28
+ assert_raises(Atom::FeedGone) do
29
+ feed.update!
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,18 @@
1
+ require "test/unit"
2
+ require "atom/feed"
3
+
4
+ class TestXHTMLContentDivConformance < Test::Unit::TestCase
5
+ def test_all
6
+ feed = Atom::Feed.new("http://www.franklinmint.fm/2006/06/divtest.atom")
7
+ feed.update!
8
+
9
+ assert_equal "<b>test</b> content", feed.entries.first.content.html
10
+
11
+ e = feed.entries.first.content.xml
12
+ assert_equal "http://www.w3.org/1999/xhtml", e.first.namespace
13
+ assert_equal "b", e.first.name
14
+ assert_equal "test", e.first.text
15
+
16
+ assert_equal " content", e.last.to_s
17
+ end
18
+ end
@@ -0,0 +1,54 @@
1
+ require "test/unit"
2
+ require "atom/feed"
3
+
4
+ class TestXMLNamespaceConformance < Test::Unit::TestCase
5
+ def test_baseline
6
+ feed = Atom::Feed.new "http://plasmasturm.org/attic/atom-tests/nondefaultnamespace-baseline.atom"
7
+ feed.update!
8
+
9
+ assert_baseline feed
10
+ end
11
+
12
+ def assert_baseline feed
13
+ assert_equal Time.parse("2006-01-18T12:26:54+01:00"), feed.updated
14
+ assert_equal "http://example.org/tests/namespace/result.html", feed.links.first["href"]
15
+
16
+ assert_equal "urn:uuid:f8195e66-863f-11da-9fcb-dd680b0526e0", feed.id
17
+
18
+ assert_equal "Aristotle Pagaltzis", feed.authors.first.name
19
+ assert_equal "pagaltzis@gmx.de", feed.authors.first.email
20
+
21
+ entry = feed.entries.first
22
+
23
+ assert_equal "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a", entry.id
24
+
25
+ assert_equal Time.parse("2006-01-18T12:26:54+01:00"), entry.updated
26
+ assert_equal "http://example.org/tests/namespace/result.html", entry.links.first["href"]
27
+
28
+ # XXX content.html should strip namespace prefixes
29
+ e = entry.content.xml
30
+
31
+ assert_equal "http://www.w3.org/1999/xhtml", e[1].namespace
32
+ assert_equal "p", e[1].name
33
+ assert_equal "For information, see:", e[1].text
34
+ end
35
+
36
+ def test_1
37
+ feed = Atom::Feed.new "http://plasmasturm.org/attic/atom-tests/nondefaultnamespace.atom"
38
+ feed.update!
39
+
40
+ assert_baseline feed
41
+ end
42
+
43
+ def test_2
44
+ feed = Atom::Feed.new "http://plasmasturm.org/attic/atom-tests/nondefaultnamespace-xhtml.atom"
45
+ feed.update!
46
+
47
+ assert_baseline feed
48
+ end
49
+
50
+ def test_3
51
+ assert(false, "I haven't written the last test")
52
+ # XXX FINISHME
53
+ end
54
+ end
data/test/runtests.rb ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
4
+
5
+ require "test/unit"
6
+
7
+ Dir["test_*.rb"].each do |test|
8
+ begin
9
+ require test
10
+ rescue LoadError
11
+ puts "skipping #{test} (LoadError)"
12
+ next
13
+ end
14
+ end
@@ -0,0 +1,91 @@
1
+ require "test/unit"
2
+ require "atom/entry"
3
+
4
+ class ConstructTest < Test::Unit::TestCase
5
+ def test_text_construct_text
6
+ entry = Atom::Entry.new
7
+
8
+ assert_nil(entry.title)
9
+ assert_equal("", entry.title.to_s)
10
+
11
+ entry.title = "<3"
12
+
13
+ assert_equal "text", entry.title["type"]
14
+ assert_equal "<3", entry.title.to_s
15
+ assert_equal "&lt;3", entry.title.html
16
+
17
+ assert_equal "'<3'#text", entry.title.inspect
18
+
19
+ title = entry.to_xml.root.children.first
20
+ assert_equal "<3", title.text
21
+ end
22
+
23
+ def test_text_construct_html
24
+ entry = Atom::Entry.new
25
+
26
+ =begin
27
+ entry.title = "<3"
28
+ entry.title["type"] = "html"
29
+
30
+ assert_equal "html", entry.title["type"]
31
+ assert_equal "<3", entry.title.to_s
32
+ assert_equal "&lt;3", entry.title.html
33
+
34
+ title = entry.to_xml.root.children.first
35
+ assert_equal "<3", title.text
36
+ =end
37
+
38
+ entry.title = "<p>pi &lt; 4?"
39
+ entry.title["type"] = "html"
40
+
41
+ assert_equal "<p>pi &lt; 4?", entry.title.to_s
42
+ assert_equal "<p>pi &lt; 4?", entry.title.html
43
+ end
44
+
45
+ def test_text_construct_xhtml
46
+ entry = Atom::Entry.new
47
+
48
+ entry.title = "<3"
49
+ assert_raises(RuntimeError) { entry.title["type"] = "xhtml" }
50
+
51
+ assert_raises(RuntimeError) do
52
+ entry.title["type"] = "application/xhtml+xml"
53
+ end
54
+
55
+ entry.title = REXML::Document.new("<div xmlns='http://www.w3.org/1999/xhtml'>&lt;3</div>").root
56
+ entry.title["type"] = "xhtml"
57
+
58
+ assert_equal "&lt;3", entry.title.to_s
59
+ assert_equal "&lt;3", entry.title.html
60
+
61
+ entry.title = "&lt;3"
62
+ entry.title["type"] = "xhtml"
63
+
64
+ assert_equal "&lt;3", entry.title.to_s
65
+ assert_equal "&lt;3", entry.title.html
66
+
67
+ entry.title = "<em>goodness</em> gracious"
68
+ entry.title["type"] = "xhtml"
69
+
70
+ assert_equal "<em>goodness</em> gracious", entry.title.to_s
71
+ assert_equal "<em>goodness</em> gracious", entry.title.html
72
+ end
73
+
74
+ def test_content
75
+ entry = Atom::Entry.new
76
+
77
+ entry.content = ""
78
+ entry.content["src"] = "http://example.com/example.svg"
79
+ entry.content["type"] = "image/svg+xml"
80
+
81
+ assert_equal("", entry.content.to_s)
82
+ end
83
+
84
+ require "date"
85
+ def test_date_construct
86
+ today = Date.today
87
+ time = Atom::Time.new today
88
+
89
+ assert_match(/^#{today}T00:00:00/, time.to_s)
90
+ end
91
+ end
data/test/test_feed.rb ADDED
@@ -0,0 +1,128 @@
1
+ require "test/unit"
2
+
3
+ require "atom/feed"
4
+ require "webrick"
5
+
6
+ class AtomFeedTest < Test::Unit::TestCase
7
+ def setup
8
+ @http = Atom::HTTP.new
9
+ @port = rand(1024) + 1024
10
+ @s = WEBrick::HTTPServer.new :Port => @port,
11
+ :Logger => WEBrick::Log.new($stderr, WEBrick::Log::FATAL),
12
+ :AccessLog => []
13
+
14
+ @test_feed =<<END
15
+ <?xml version="1.0" encoding="utf-8"?>
16
+ <feed xmlns="http://www.w3.org/2005/Atom">
17
+ <title>Example Feed</title>
18
+ <link href="http://example.org/"/>
19
+ <updated>2003-12-13T18:30:02Z</updated>
20
+ <author>
21
+ <name>John Doe</name>
22
+ </author>
23
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
24
+
25
+ <entry>
26
+ <title>Atom-Powered Robots Run Amok</title>
27
+ <link href="http://example.org/2003/12/13/atom03"/>
28
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
29
+ <updated>2003-12-13T18:30:02Z</updated>
30
+ <summary>Some text.</summary>
31
+ </entry>
32
+ </feed>
33
+ END
34
+ end
35
+
36
+ def test_merge
37
+ feed1 = Atom::Feed.new
38
+
39
+ feed1.title = "title"
40
+
41
+ feed1.subtitle = "<br>"
42
+ feed1.subtitle["type"] = "html"
43
+
44
+ a = feed1.authors.new
45
+ a.name = "test"
46
+
47
+ feed2 = Atom::Feed.new
48
+
49
+ feed = feed1.merge(feed2)
50
+
51
+ assert_equal "text", feed.title["type"]
52
+ assert_equal "title", feed.title.to_s
53
+
54
+ assert_equal "html", feed.subtitle["type"]
55
+ assert_equal "<br>", feed.subtitle.to_s
56
+
57
+ assert_equal 1, feed.authors.length
58
+ assert_equal "test", feed.authors.first.name
59
+ end
60
+
61
+ def test_update
62
+ @s.mount_proc("/") do |req,res|
63
+ res.content_type = "application/atom+xml"
64
+ res.body = @test_feed
65
+
66
+ @s.stop
67
+ end
68
+
69
+ feed = Atom::Feed.new "http://localhost:#{@port}/"
70
+
71
+ assert_equal nil, feed.title
72
+ assert_equal nil, feed.id
73
+ assert_equal [], feed.entries
74
+
75
+ one_shot
76
+
77
+ feed.update!
78
+
79
+ assert_equal "Example Feed", feed.title.to_s
80
+ assert_equal "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6", feed.id
81
+ assert_equal 1, feed.entries.length
82
+ end
83
+
84
+ def test_conditional_get
85
+ @s.mount_proc("/") do |req,res|
86
+ assert_nil req["If-None-Match"]
87
+ assert_nil req["If-Modified-Since"]
88
+
89
+ res["Etag"] = '"xyzzy"'
90
+ res["Last-Modified"] = 'Wed, 15 Nov 1995 04:58:08 GMT'
91
+ res.content_type = "application/atom+xml"
92
+ res.body = @test_feed
93
+
94
+ @s.stop
95
+ end
96
+
97
+ feed = Atom::Feed.new "http://localhost:#{@port}/"
98
+
99
+ assert_equal 0, feed.entries.length
100
+ assert_equal nil, feed.etag
101
+ assert_equal nil, feed.last_modified
102
+
103
+ one_shot
104
+
105
+ feed.update!
106
+
107
+ assert_equal 1, feed.entries.length
108
+ assert_equal '"xyzzy"', feed.etag
109
+ assert_equal 'Wed, 15 Nov 1995 04:58:08 GMT', feed.last_modified
110
+
111
+ @s.mount_proc("/") do |req,res|
112
+ assert_equal '"xyzzy"', req["If-None-Match"]
113
+ assert_equal 'Wed, 15 Nov 1995 04:58:08 GMT', req["If-Modified-Since"]
114
+
115
+ res.status = 304
116
+ res.body = "this hasn't been modified"
117
+
118
+ @s.stop
119
+ end
120
+
121
+ one_shot
122
+ feed.update!
123
+
124
+ assert_equal 1, feed.entries.length
125
+ end
126
+
127
+ def one_shot; Thread.new { @s.start }; end
128
+ end