yyyc514-syndication 0.6.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,79 @@
1
+ # Copyright � mathew <meta@pobox.com> 2006.
2
+ # Licensed under the same terms as Ruby.
3
+
4
+ require 'syndication/rss'
5
+ require 'test/unit'
6
+ require 'syndication/dublincore'
7
+ require 'syndication/content'
8
+ require 'syndication/podcast'
9
+ require 'syndication/feedburner'
10
+
11
+ module Syndication
12
+
13
+ # This class contains the unit tests for the Syndication module.
14
+ class Tests < Test::Unit::TestCase
15
+
16
+ # A set of minimal assertions that can be applied to every well-formed parsed
17
+ # feed.
18
+ def baseline_rss_assertions(feed)
19
+ assert_not_nil(feed)
20
+ assert_kind_of(Syndication::RSS::Feed, feed)
21
+ loi = feed.items
22
+ assert_not_nil(loi)
23
+ assert_kind_of(Array, loi)
24
+ assert(loi.length >= 1)
25
+ assert_not_nil(loi[0])
26
+ assert_not_nil(loi[0].description)
27
+ end
28
+
29
+ def test_feedburner
30
+ xml = <<-EOF
31
+ <?xml version="1.0" encoding="UTF-8"?>
32
+ <?xml-stylesheet href="http://feeds.sfgate.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?>
33
+ <?xml-stylesheet href="http://feeds.sfgate.com/~d/styles/itemcontent.css" type="text/css" media="screen"?>
34
+ <rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
35
+ <channel>
36
+ <title>SFGate: Top News Stories</title>
37
+ <link>http://www.sfgate.com/</link>
38
+ <description>Top news stories. From SFGate.com: the Bay Area's home page, online home of the San Francisco Chronicle and much more.</description>
39
+ <language>en-us</language>
40
+ <copyright>Copyright 2006 Hearst Communications, Inc.</copyright>
41
+ <managingEditor>ed@sfgate.com (SFGate Editorial staff)</managingEditor>
42
+ <webMaster>support@sfgate.com (SFGate technical support)</webMaster>
43
+ <lastBuildDate>Sun, 09 Jul 2006 14:21:10 PDT</lastBuildDate>
44
+ <category>News</category>
45
+ <category>Newspapers</category>
46
+ <category>San Francisco</category>
47
+ <category>San Francisco Bay Area</category>
48
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
49
+ <image>
50
+ <url>http://www.sfgate.com/templates/types/syndication/pages/rss/graphics/sfgate_logo.png</url>
51
+ <title>SFGate: Top News Stories</title>
52
+ <link>http://www.sfgate.com/</link>
53
+ </image>
54
+ <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://www.sfgate.com/rss/feeds/news.xml" type="application/rss+xml" /><feedburner:browserFriendly>This is an RSS feed, but with the headlines made visible. Choose one of the buttons to add this feed to your favorite RSS reader.</feedburner:browserFriendly>
55
+ <item>
56
+ <title><![CDATA[Italy Beats France for 4th World Cup Title]]></title>
57
+ <link>http://feeds.sfgate.com/sfgate/rss/feeds/news?m=4300</link>
58
+ <description>Italy let France do nearly anything it wanted Sunday, except win the World Cup. That belongs to the Azzurri, 5-3 in a shootout after a 1-1 draw. Outplayed for an hour and into extra time, the Italians won it after French captain Zinedine Zidane was...&lt;img src="http://feeds.sfgate.com/sfgate/rss/feeds/news?g=4300"/&gt;</description>
59
+ <author><![CDATA[By BARRY WILNER, AP Sports Writer]]></author>
60
+ <pubDate>Sun, 09 Jul 2006 14:14:59 PDT</pubDate>
61
+
62
+ <guid isPermaLink="false">/n/a/2006/07/09/sports/s134544D82.DTL</guid>
63
+ <feedburner:origLink>http://www.sfgate.com/cgi-bin/article.cgi?f=/n/a/2006/07/09/sports/s134544D82.DTL&amp;feed=rss.news</feedburner:origLink>
64
+ </item>
65
+ </channel>
66
+ </rss>
67
+ EOF
68
+ f = Syndication::RSS::Parser.new.parse(xml)
69
+ il = f.items
70
+ assert_not_nil(il)
71
+ assert(il.length == 1)
72
+ i = il.first
73
+ assert_not_nil(i.feedburner_origlink)
74
+ assert(i.feedburner_origlink == "http://www.sfgate.com/cgi-bin/article.cgi?f=/n/a/2006/07/09/sports/s134544D82.DTL&feed=rss.news")
75
+ end
76
+
77
+ end
78
+
79
+ end
data/test/google.rb ADDED
@@ -0,0 +1,91 @@
1
+ # Copyright © mathew <meta@pobox.com> 2005.
2
+ # Licensed under the same terms as Ruby.
3
+
4
+ require 'syndication/atom'
5
+ require 'syndication/google'
6
+ require 'test/unit'
7
+ require 'pp'
8
+
9
+ module Syndication
10
+
11
+ # This class contains the unit tests for the Syndication module.
12
+ class Tests < Test::Unit::TestCase
13
+
14
+ # A set of minimal assertions that can be applied to every well-formed parsed
15
+ # feed.
16
+ def baseline_assertions(feed)
17
+ assert_not_nil(feed, 'Parser returned nil')
18
+ assert_kind_of(Syndication::Atom::Feed, feed)
19
+ assert_not_nil(feed.title, 'Feed#title was nil')
20
+ assert_not_nil(feed.id, 'Feed#id was nil')
21
+ assert_not_nil(feed.updated, 'Feed#updated was nil')
22
+ assert_kind_of(DateTime, feed.updated)
23
+ assert(feed.entries.length > 0, 'No entries in feed')
24
+ for entry in feed.entries
25
+ assert_not_nil(entry.title, 'Entry#title was nil')
26
+ assert_not_nil(entry.id, 'Entry#id was nil')
27
+ assert(entry.links.length > 0, 'No links in entry')
28
+ assert_not_nil(entry.links[0], 'Entry#links[0] was nil')
29
+ assert_not_nil(entry.updated, 'Entry#updated was nil')
30
+ assert_kind_of(DateTime, entry.updated)
31
+ end
32
+ end
33
+
34
+ # Minimal test
35
+ def test_atom_google
36
+ xml = <<EOF
37
+ <feed xmlns='http://www.w3.org/2005/Atom'
38
+ xmlns:gd='http://schemas.google.com/g/2005'>
39
+ <id>http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full</id>
40
+ <updated>2006-03-29T07:35:59.000Z</updated>
41
+ <title type='text'>Jo March</title>
42
+ <subtitle type='text'>This is my main calendar.</subtitle>
43
+ <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'
44
+ href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full'></link>
45
+ <link rel='self' type='application/atom+xml'
46
+ href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full'></link>
47
+ <author>
48
+ <name>Jo March</name>
49
+ <email>jo@gmail.com</email>
50
+ </author>
51
+ <generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>
52
+ <gd:where valueString='California'></gd:where>
53
+ <entry>
54
+ <id>http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID</id>
55
+ <published>2006-03-30T22:00:00.000Z</published>
56
+ <updated>2006-03-28T05:47:31.000Z</updated>
57
+ <category scheme='http://schemas.google.com/g/2005#kind'
58
+ term='http://schemas.google.com/g/2005#event'></category>
59
+ <title type='text'>Lunch with Darcy</title>
60
+ <content type='text'>Lunch to discuss future plans.</content>
61
+ <link rel='alternate' type='text/html'
62
+ href='http://www.google.com/calendar/event?eid=aTJxcnNqbW9tcTJnaTE5cnMybmEwaW04bXMgbWFyY2guam9AZ21haWwuY29t'
63
+ title='alternate'></link>
64
+ <link rel='self' type='application/atom+xml'
65
+ href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID'></link>
66
+ <author>
67
+ <name>Jo March</name>
68
+ <email>jo@gmail.com</email>
69
+ </author>
70
+ <gd:transparency
71
+ value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency>
72
+ <gd:eventStatus
73
+ value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus>
74
+ <gd:comments>
75
+ <gd:feedLink
76
+ href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID/comments/'></gd:feedLink>
77
+ </gd:comments>
78
+ <gd:when startTime='2006-03-30T22:00:00.000Z'
79
+ endTime='2006-03-30T23:00:00.000Z'></gd:when>
80
+ <gd:where></gd:where>
81
+ </entry>
82
+ </feed>
83
+ EOF
84
+ f = Syndication::Atom::Parser.new.parse(xml)
85
+ baseline_assertions(f)
86
+ entry = f.entries.first
87
+ assert(entry.gd_when.to_s == "2006-03-30T22:00:00Z2006-03-30T23:00:00Z")
88
+ end
89
+
90
+ end
91
+ end
data/test/rsstest.rb ADDED
@@ -0,0 +1,422 @@
1
+ # Copyright � mathew <meta@pobox.com> 2005.
2
+ # Licensed under the same terms as Ruby.
3
+ #
4
+ # $Header: /var/cvs/syndication/syndication/test/rsstest.rb,v 1.4 2005/10/23 23:00:59 meta Exp $
5
+
6
+ require 'syndication/rss'
7
+ require 'test/unit'
8
+ require 'syndication/dublincore'
9
+ require 'syndication/content'
10
+ require 'syndication/podcast'
11
+
12
+ module Syndication
13
+
14
+ # This class contains the unit tests for the Syndication module.
15
+ class Tests < Test::Unit::TestCase
16
+
17
+ # A set of minimal assertions that can be applied to every well-formed parsed
18
+ # feed.
19
+ def baseline_rss_assertions(feed)
20
+ assert_not_nil(feed)
21
+ assert_kind_of(Syndication::RSS::Feed, feed)
22
+ loi = feed.items
23
+ assert_not_nil(loi)
24
+ assert_kind_of(Array, loi)
25
+ assert(loi.length >= 1)
26
+ assert_not_nil(loi[0])
27
+ assert_not_nil(loi[0].description)
28
+ end
29
+
30
+ # Test a minimal well-formed RSS2.0 feed
31
+ def test_rss2_wf_minimal
32
+ xml = <<-EOF
33
+ <rss version="2.0">
34
+ <channel>
35
+ <title>I like coffee</title>
36
+ <link>http://www.coffeegeek.com/</link>
37
+ <description>Hand over the latte &amp; nobody gets hurt.</description>
38
+ </channel>
39
+ <item>
40
+ <description>A day without coffee is incomplete.</description>
41
+ </item>
42
+ </rss>
43
+ EOF
44
+ f = Syndication::RSS::Parser.new.parse(xml)
45
+ baseline_rss_assertions(f)
46
+ assert(f.channel.title == 'I like coffee')
47
+ assert(f.channel.link == 'http://www.coffeegeek.com/')
48
+ assert(f.channel.description == 'Hand over the latte & nobody gets hurt.')
49
+ assert(f.items.first.description == 'A day without coffee is incomplete.')
50
+ c = f.channel
51
+ assert_not_nil(c)
52
+ assert_kind_of(Syndication::RSS::Channel, c)
53
+ assert_not_nil(c.title)
54
+ assert_not_nil(c.link)
55
+ assert_not_nil(c.description)
56
+ end
57
+
58
+ # Test a minimal well-formed RSS1.0 feed
59
+ def test_rss1_wf_minimal
60
+ xml = <<-EOF
61
+ <?xml version="1.0"?>
62
+ <rdf:RDF
63
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
64
+ xmlns="http://purl.org/rss/1.0/">
65
+ <channel rdf:about="http://www.otternet.com/">
66
+ <title>OtterNet</title>
67
+ <link>http://www.otternet.com/</link>
68
+ <description>Otternet has pages &amp; pages of information about otters.</description>
69
+ </channel>
70
+ <item rdf:about="http://www.otternet.com/species/seaotter.htm">
71
+ <title>The Sea Otter</title>
72
+ <link>http://www.otternet.com/species/seaotter.htm</link>
73
+ <description>The enticingly cute enhydra lontris.</description>
74
+ </item>
75
+ </rdf:RDF>
76
+ EOF
77
+ f = Syndication::RSS::Parser.new.parse(xml)
78
+ baseline_rss_assertions(f)
79
+ assert(f.channel.title == 'OtterNet')
80
+ assert(f.channel.link == 'http://www.otternet.com/')
81
+ assert(f.channel.description == 'Otternet has pages & pages of information about otters.')
82
+ assert(f.items.first.title == 'The Sea Otter')
83
+ assert(f.items.first.link == 'http://www.otternet.com/species/seaotter.htm')
84
+ assert(f.items.first.description == 'The enticingly cute enhydra lontris.')
85
+ c = f.channel
86
+ assert_not_nil(c)
87
+ assert_kind_of(Syndication::RSS::Channel, c)
88
+ assert_not_nil(c.title)
89
+ assert_not_nil(c.link)
90
+ assert_not_nil(c.description)
91
+ end
92
+
93
+ # Test a well-formed RSS2 feed with every element possible and more than
94
+ # one item
95
+ def test_rss2_wf_full
96
+ xml = <<-EOF
97
+ <rss version="2">
98
+ <channel>
99
+ <title>Example Feed</title>
100
+ <link>http://www.example.com/</link>
101
+ <description>This is merely an example.</description>
102
+ <language>en-us</language>
103
+ <copyright>Copyright 2004 The Example Corporation.</copyright>
104
+ <managingEditor>editor@example.com</managingEditor>
105
+ <webMaster>webmaster@example.com</webMaster>
106
+ <pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>
107
+ <lastBuildDate>Sat, 7 Sep 02 13:14:15 -0600</lastBuildDate>
108
+ <category>examples</category>
109
+ <category>boring</category>
110
+ <generator>vim of course</generator>
111
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
112
+ <cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="pingMe" protocol="soap"/>
113
+ <ttl>90</ttl>
114
+ <image>
115
+ <title>Example Inc</title>
116
+ <url>http://www.example.com/images/logo.jpg</url>
117
+ <link>http://www.example.com</link>
118
+ <width>42</width>
119
+ <height>23</height>
120
+ </image>
121
+ <rating>(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))</rating>
122
+ <textInput>
123
+ <title>Submit</title>
124
+ <description>Enter keywords</description>
125
+ <name>SearchKeywords</name>
126
+ <link>http://www.example.com/cgi-bin/search.pl</link>
127
+ </textInput>
128
+ <skipHours>
129
+ <hour>0</hour>
130
+ <hour>23</hour>
131
+ </skipHours>
132
+ <skipDays>
133
+ <day>Monday</day>
134
+ <day>Sunday</day>
135
+ </skipDays>
136
+ <item>
137
+ <title>Our stock price shot up</title>
138
+ <link>http://www.example.com/news/2.html</link>
139
+ <description>We were hyped in the press!</description>
140
+ </item>
141
+ <item>
142
+ <title>A dull example of little value.</title>
143
+ <link>http://www.example.com/news/1.html</link>
144
+ <description>If this was any less interesting, it would be amazing.</description>
145
+ <author>fred@example.com</author>
146
+ <pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>
147
+ <category>dull</category>
148
+ <category>amazingly</category>
149
+ <comments>http://www.example.com/news/comments/1.html</comments>
150
+ <enclosure url="http://www.example.com/mp3/advertisement.mp3" length="123987" type="audio/mpeg" />
151
+ <guid>4asd98dgf9a74@example.com</guid>
152
+ <source url="http://www.example.com/news.xml">Example News</source>
153
+ </item>
154
+ </channel>
155
+ </rss>
156
+ EOF
157
+ f = Syndication::RSS::Parser.new.parse(xml)
158
+ baseline_rss_assertions(f)
159
+ for elem in %w(title link description language copyright managingeditor webmaster pubdate lastbuilddate category generator docs cloud ttl textinput rating skiphours skipdays)
160
+ assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
161
+ assert(f.channel.send(elem).to_s.length > 0)
162
+ end
163
+ items = f.items
164
+ assert(items.length == 2)
165
+ i = items.last
166
+ for elem in %w(title link description author pubdate category comments enclosure guid source)
167
+ assert_not_nil(i.send(elem), "feed.channel.item[1].#{elem} is nil, it shouldn't be")
168
+ end
169
+ cats = i.category
170
+ assert(cats.length == 2)
171
+ assert(cats.first == 'dull')
172
+ assert(cats.last == 'amazingly')
173
+ assert(f.channel.skiphours.length == 2)
174
+ assert(f.channel.skiphours.first == 0)
175
+ assert(f.channel.skiphours.last == 23)
176
+ assert(f.channel.pubdate.kind_of?(DateTime))
177
+ assert(f.channel.lastbuilddate.kind_of?(DateTime))
178
+ assert(f.channel.pubdate.mday == 7)
179
+ assert(f.channel.pubdate.month == 9)
180
+ assert(f.channel.lastbuilddate.mday == 7)
181
+ assert(f.channel.lastbuilddate.month == 9)
182
+ c = f.channel
183
+ assert_not_nil(c)
184
+ assert_kind_of(Syndication::RSS::Channel, c)
185
+ assert_not_nil(c.title)
186
+ assert_not_nil(c.link)
187
+ assert_not_nil(c.description)
188
+ end
189
+
190
+ # Test a well-formed RSS 1.0 feed with every element possible, more
191
+ # than one item, and rdf:resource links in the channel
192
+ def test_rss1_wf_full
193
+ xml = <<-EOF
194
+ <rdf:RDF
195
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
196
+ xmlns="http://purl.org/rss/1.0/">
197
+ <channel>
198
+ <title>Example Dot Org</title>
199
+ <link>http://www.example.org</link>
200
+ <description>the Example Organization web site</description>
201
+ <image rdf:resource="http://www.example.org/images/logo.gif"/>
202
+ <items>
203
+ <rdf:Seq>
204
+ <rdf:li resource="http://www.example.org/items/1"/>
205
+ <rdf:li resource="http://www.example.org/items/2"/>
206
+ </rdf:Seq>
207
+ </items>
208
+ <textinput rdf:resource="http://www.example.org/cgi-bin/input.pl"/>
209
+ </channel>
210
+ <textinput rdf:about="http://www.example.org/cgi-bin/input.pl">
211
+ <title>Search example.org</title>
212
+ <description>Search the example.org web site</description>
213
+ <name>query</name>
214
+ <link>http://www.example.org/cgi-bin/input.pl</link>
215
+ </textinput>
216
+ <image rdf:about="http://www.example.org/images/logo.gif">
217
+ <title>Example.org logo</title>
218
+ <link>http://www.example.org/</link>
219
+ <url>http://www.example.org/images/logo.gif</url>
220
+ </image>
221
+ <item rdf:about="http://www.example.org/items/1">
222
+ <title>Welcome</title>
223
+ <link>http://www.example.org/items/1</link>
224
+ <description>Welcome to our new news feed</description>
225
+ </item>
226
+ <item rdf:about="http://www.example.org/items/2">
227
+ <title>New Status Update</title>
228
+ <link>http://www.example.org/items/1</link>
229
+ <description>News about the Example project</description>
230
+ </item>
231
+ </rdf:RDF>
232
+ EOF
233
+ f = Syndication::RSS::Parser.new.parse(xml)
234
+ baseline_rss_assertions(f)
235
+ for elem in %w(title link description textinput)
236
+ assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
237
+ assert(f.channel.send(elem).to_s.length > 0)
238
+ end
239
+ il = f.items
240
+ assert(il.length == 2)
241
+ i = il.last
242
+ assert(i.link == 'http://www.example.org/items/1')
243
+ assert(i.title == 'New Status Update')
244
+ assert(i.description == 'News about the Example project')
245
+ assert(f.textinput.title == 'Search example.org')
246
+ f.channel.image.strip
247
+ assert(f.image.url == 'http://www.example.org/images/logo.gif')
248
+ c = f.channel
249
+ assert_not_nil(c)
250
+ assert_kind_of(Syndication::RSS::Channel, c)
251
+ assert_not_nil(c.title)
252
+ assert_not_nil(c.link)
253
+ assert_not_nil(c.description)
254
+ end
255
+
256
+ # Test HTML encoded content in RSS 1.0 and namespace remapping
257
+ def test_rss1_content
258
+ xml = <<-EOF
259
+ <?xml version="1.0"?>
260
+ <rdf:RDF
261
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
262
+ xmlns:html="http://purl.org/rss/1.0/modules/content/"
263
+ xmlns="http://purl.org/rss/1.0/">
264
+ <channel rdf:about="http://www.otternet.com/">
265
+ <title>OtterNet</title>
266
+ <link>http://www.otternet.com/</link>
267
+ <description>Otternet has dozens of pages of information about otters.</description>
268
+ <content:encoded><![CDATA[<p><cite>OtterNet</cite> has <em>dozens</em> of pages of information about otters.</p>]]></content:encoded>
269
+ </channel>
270
+ <item rdf:about="http://www.otternet.com/species/seaotter.htm">
271
+ <title>The Sea Otter</title>
272
+ <link>http://www.otternet.com/species/seaotter.htm</link>
273
+ <description>The enticingly cute enhydra lontris.</description>
274
+ <html:encoded>The enticingly cute &lt;i&gt;enhydra lontris&lt;/i&gt;</html:encoded>
275
+ </item>
276
+ <item rdf:about="http://www.ruby-lang.org/">
277
+ <title>Ruby</title>
278
+ <link>http://www.ruby-lang.org/</link>
279
+ <description>There's this language called Ruby, you may have heard of it.</description>
280
+ <html:encoded>There's this language called &lt;strong&gt;Ruby&lt;/strong&gt;, you &lt;em&gt;may&lt;/em&gt; have heard of it.</html:encoded>
281
+ </item>
282
+ </rdf:RDF>
283
+ EOF
284
+ f = Syndication::RSS::Parser.new.parse(xml)
285
+ baseline_rss_assertions(f)
286
+ il = f.items
287
+ assert(il.length == 2)
288
+ i1 = il.first
289
+ i2 = il.last
290
+ assert_not_nil(i1.content_encoded, "content_encoded nil, shouldn't be")
291
+ assert_not_nil(i2.content_encoded, "content_encoded nil, shouldn't be")
292
+ assert(i1.content_encoded == 'The enticingly cute <i>enhydra lontris</i>')
293
+ assert(i1.content_decoded == 'The enticingly cute <i>enhydra lontris</i>')
294
+ assert(i2.content_decoded == "There's this language called <strong>Ruby</strong>, you <em>may</em> have heard of it.")
295
+ c = f.channel
296
+ assert(c.content_encoded == '<![CDATA[<p><cite>OtterNet</cite> has <em>dozens</em> of pages of information about otters.</p>]]>')
297
+ assert(c.content_decoded == '<p><cite>OtterNet</cite> has <em>dozens</em> of pages of information about otters.</p>')
298
+ assert_not_nil(c)
299
+ assert_kind_of(Syndication::RSS::Channel, c)
300
+ assert_not_nil(c.title)
301
+ assert_not_nil(c.link)
302
+ assert_not_nil(c.description)
303
+ end
304
+
305
+ # Test iTunes-specific duration parsing
306
+ def test_itunes
307
+ i = Syndication::RSS::Item.new(nil)
308
+ i.itunes_duration = "12:34:56"
309
+ assert(i.itunes_duration == 45296, "Duration computed incorrectly")
310
+ i.itunes_duration = "5:43:21"
311
+ assert(i.itunes_duration == 20601, "Duration computed incorrectly")
312
+ i.itunes_duration = "20:01"
313
+ assert(i.itunes_duration == 1201, "Duration computed incorrectly")
314
+ i.itunes_duration = "3:52"
315
+ assert(i.itunes_duration == 232, "Duration computed incorrectly")
316
+ end
317
+
318
+ # Test a well-formed RSS2 feed with every element possible and more than
319
+ # one item, with all kinds of stuff CDATA escaped.
320
+ def test_rss2_wf_full_cdata
321
+ xml = <<-EOF
322
+ <rss version="2">
323
+ <channel>
324
+ <title><![CDATA[Example Feed]]></title>
325
+ <link>http://www.example.com/</link>
326
+ <description><![CDATA[This is merely an example.]]></description>
327
+ <language>en-us</language>
328
+ <copyright>Copyright 2004 The Example Corporation.</copyright>
329
+ <managingEditor>editor@example.com</managingEditor>
330
+ <webMaster>webmaster@example.com</webMaster>
331
+ <pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>
332
+ <lastBuildDate>Sat, 7 Sep 02 13:14:15 -0600</lastBuildDate>
333
+ <category>examples</category>
334
+ <category>boring</category>
335
+ <generator>vim of course</generator>
336
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
337
+ <cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="pingMe" protocol="soap"/>
338
+ <ttl>90</ttl>
339
+ <image>
340
+ <title><![CDATA[Example Inc]]></title>
341
+ <url>http://www.example.com/images/logo.jpg</url>
342
+ <link>http://www.example.com</link>
343
+ <width>42</width>
344
+ <height>23</height>
345
+ </image>
346
+ <rating>(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))</rating>
347
+ <textInput>
348
+ <title>Submit</title>
349
+ <description>Enter keywords</description>
350
+ <name>SearchKeywords</name>
351
+ <link>http://www.example.com/cgi-bin/search.pl</link>
352
+ </textInput>
353
+ <skipHours>
354
+ <hour>0</hour>
355
+ <hour>23</hour>
356
+ </skipHours>
357
+ <skipDays>
358
+ <day>Monday</day>
359
+ <day>Sunday</day>
360
+ </skipDays>
361
+ <item>
362
+ <title>Our stock price shot up</title>
363
+ <link>http://www.example.com/news/2.html</link>
364
+ <description>We were hyped in the press!</description>
365
+ </item>
366
+ <item>
367
+ <title><![CDATA[Unencoded < > and & are allowed.]]></title>
368
+ <link><![CDATA[http://www.example.com/news/1.html]]></link>
369
+ <description><![CDATA[If this was any less interesting, it would be amazing.]]></description>
370
+ <author><![CDATA[fred@example.com]]></author>
371
+ <pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>
372
+ <category>dull</category>
373
+ <category>amazingly</category>
374
+ <comments>http://www.example.com/news/comments/1.html</comments>
375
+ <enclosure url="http://www.example.com/mp3/advertisement.mp3" length="123987" type="audio/mpeg" />
376
+ <guid>4asd98dgf9a74@example.com</guid>
377
+ <source url="http://www.example.com/news.xml">Example News</source>
378
+ </item>
379
+ </channel>
380
+ </rss>
381
+ EOF
382
+ f = Syndication::RSS::Parser.new.parse(xml)
383
+ baseline_rss_assertions(f)
384
+ for elem in %w(title link description language copyright managingeditor webmaster pubdate lastbuilddate category generator docs cloud ttl textinput rating skiphours skipdays)
385
+ assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
386
+ assert(f.channel.send(elem).to_s.length > 0)
387
+ end
388
+ # Check CDATA is decoded properly
389
+ assert(f.channel.title == 'Example Feed')
390
+ assert(f.channel.description == 'This is merely an example.')
391
+ items = f.items
392
+ assert(items.length == 2)
393
+ i = items.last
394
+ for elem in %w(title link description author pubdate category comments enclosure guid source)
395
+ assert_not_nil(i.send(elem), "feed.channel.item[1].#{elem} is nil, it shouldn't be")
396
+ end
397
+ cats = i.category
398
+ assert(i.title == 'Unencoded < > and & are allowed.')
399
+ assert(i.link == 'http://www.example.com/news/1.html')
400
+ assert(cats.length == 2)
401
+ assert(cats.first == 'dull')
402
+ assert(cats.last == 'amazingly')
403
+ assert(f.channel.skiphours.length == 2)
404
+ assert(f.channel.skiphours.first == 0)
405
+ assert(f.channel.skiphours.last == 23)
406
+ assert(f.channel.pubdate.kind_of?(DateTime))
407
+ assert(f.channel.lastbuilddate.kind_of?(DateTime))
408
+ assert(f.channel.pubdate.mday == 7)
409
+ assert(f.channel.pubdate.month == 9)
410
+ assert(f.channel.lastbuilddate.mday == 7)
411
+ assert(f.channel.lastbuilddate.month == 9)
412
+ c = f.channel
413
+ assert_not_nil(c)
414
+ assert_kind_of(Syndication::RSS::Channel, c)
415
+ assert_not_nil(c.title)
416
+ assert_not_nil(c.link)
417
+ assert_not_nil(c.description)
418
+ end
419
+
420
+ end
421
+
422
+ end
@@ -0,0 +1,86 @@
1
+ # Copyright � mathew <meta@pobox.com> 2005.
2
+ # Licensed under the same terms as Ruby.
3
+ #
4
+ # $Header: /var/cvs/syndication/syndication/test/tagsouptest.rb,v 1.2 2005/10/17 20:06:51 meta Exp $
5
+
6
+ require 'syndication/tagsoup'
7
+ require 'test/unit'
8
+ require 'rexml/document'
9
+
10
+ module Syndication
11
+
12
+ # This class contains the unit tests for the Syndication module.
13
+ class Tests < Test::Unit::TestCase
14
+
15
+ def tag_start(x, pairs)
16
+ @events << "tag_start(#{x.strip})"
17
+ lst = nil
18
+ if pairs
19
+ for p in pairs
20
+ if lst
21
+ lst = lst + ","
22
+ else
23
+ lst = ""
24
+ end
25
+ lst << "#{p[0]}=#{p[1]}"
26
+ end
27
+ @events << "attrs(#{lst})"
28
+ end
29
+ end
30
+
31
+ def tag_end(x)
32
+ @events << "tag_end(#{x.strip})"
33
+ end
34
+
35
+ def text(x)
36
+ @events << "text(#{x.strip})"
37
+ end
38
+
39
+ # Minimal test
40
+ def test_tagsoup
41
+ xml = <<-EOF
42
+ <a>
43
+ <b>one
44
+ <c></c></b>
45
+ <d arg1="alpha">two</d>
46
+ <e arg2='beta'>
47
+ three&lt;four&#99;&trade;
48
+ </e>
49
+ </a>
50
+ <feed xmlns="http://www.w3.org/2005/Atom">
51
+ <title>One good turn usually gets most of the blanket.</title>
52
+ <updated>2005-08-20T21:14:38Z</updated>
53
+ <id>urn:uuid:035d3aa3022c1b1b2a17e37ae2dcc376</id>
54
+ <entry>
55
+ <title>Quidquid latine dictum sit, altum viditur.</title>
56
+ <link href="http://example.com/05/08/20/2114.html"/>
57
+ <id>urn:uuid:89d96d76a99426264f6f1f520c1b93c2</id>
58
+ <updated>2005-08-20T21:14:38Z</updated>
59
+ </entry>
60
+ </feed>
61
+ EOF
62
+ @events = Array.new
63
+ Syndication::TagSoup.parse_stream(xml, self)
64
+ @tagsoup = @events
65
+ @events = Array.new
66
+ REXML::Document.parse_stream(xml, self)
67
+ @rexml = @events
68
+ #puts "REXML\n-----"
69
+ #pp @rexml
70
+ #puts "\nTAGSOUP\n-------"
71
+ #pp @tagsoup
72
+ errs = false
73
+ for tsevt in @tagsoup
74
+ rxevt = @rexml.shift
75
+ if rxevt
76
+ if tsevt.to_s != rxevt.to_s
77
+ errs = true
78
+ #puts "TagSoup: [#{tsevt}]\nREXML: [#{rxevt}]"
79
+ end
80
+ end
81
+ end
82
+ assert(!errs, "TagSoup and REXML parse results didn't match")
83
+ end
84
+
85
+ end
86
+ end