Class Syndication::Tests
In: test/tagsouptest.rb
test/atomtest.rb
test/feedburntest.rb
test/google.rb
test/rsstest.rb
Parent: Test::Unit::TestCase

This class contains the unit tests for the Syndication module.

Methods

Public Instance methods

A set of minimal assertions that can be applied to every well-formed parsed feed.

[Source]

# File test/google.rb, line 16
    def baseline_assertions(feed)
      assert_not_nil(feed, 'Parser returned nil')
      assert_kind_of(Syndication::Atom::Feed, feed)
      assert_not_nil(feed.title, 'Feed#title was nil')
      assert_not_nil(feed.id, 'Feed#id was nil')
      assert_not_nil(feed.updated, 'Feed#updated was nil')
      assert_kind_of(DateTime, feed.updated)
      assert(feed.entries.length > 0, 'No entries in feed')
      for entry in feed.entries
        assert_not_nil(entry.title, 'Entry#title was nil')
        assert_not_nil(entry.id, 'Entry#id was nil')
        assert(entry.links.length > 0, 'No links in entry')
        assert_not_nil(entry.links[0], 'Entry#links[0] was nil')
        assert_not_nil(entry.updated, 'Entry#updated was nil')
        assert_kind_of(DateTime, entry.updated)
      end
    end

A set of minimal assertions that can be applied to every well-formed parsed feed.

[Source]

# File test/atomtest.rb, line 16
    def baseline_atom_assertions(feed)
      assert_not_nil(feed, 'Parser returned nil')
      assert_kind_of(Syndication::Atom::Feed, feed)
      assert_not_nil(feed.title, 'Feed#title was nil')
      assert_not_nil(feed.id, 'Feed#id was nil')
      assert_not_nil(feed.updated, 'Feed#updated was nil')
      assert_kind_of(DateTime, feed.updated)
      assert(feed.entries.length > 0, 'No entries in feed')
      for entry in feed.entries
        assert_not_nil(entry.title, 'Entry#title was nil')
        assert_not_nil(entry.id, 'Entry#id was nil')
        assert(entry.links.length > 0, 'No links in entry')
        assert_not_nil(entry.links[0], 'Entry#links[0] was nil')
        assert_not_nil(entry.updated, 'Entry#updated was nil')
        assert_kind_of(DateTime, entry.updated)
      end
    end

A set of minimal assertions that can be applied to every well-formed parsed feed.

[Source]

# File test/rsstest.rb, line 19
  def baseline_rss_assertions(feed)
    assert_not_nil(feed)
    assert_kind_of(Syndication::RSS::Feed, feed)
    loi = feed.items
    assert_not_nil(loi)
    assert_kind_of(Array, loi)
    assert(loi.length >= 1)
    assert_not_nil(loi[0])
    assert_not_nil(loi[0].description)
  end

A set of minimal assertions that can be applied to every well-formed parsed feed.

[Source]

# File test/feedburntest.rb, line 18
    def baseline_rss_assertions(feed)
      assert_not_nil(feed)
      assert_kind_of(Syndication::RSS::Feed, feed)
      loi = feed.items
      assert_not_nil(loi)
      assert_kind_of(Array, loi)
      assert(loi.length >= 1)
      assert_not_nil(loi[0])
      assert_not_nil(loi[0].description)
    end

[Source]

# File test/tagsouptest.rb, line 31
    def tag_end(x)
      @events << "tag_end(#{x.strip})"
    end

[Source]

# File test/tagsouptest.rb, line 15
    def tag_start(x, pairs)
      @events << "tag_start(#{x.strip})"
      lst = nil
      if pairs
        for p in pairs
          if lst
            lst = lst + ","
          else
            lst = ""
          end
          lst << "#{p[0]}=#{p[1]}"
        end
        @events << "attrs(#{lst})"
      end
    end

Minimal test

[Source]

# File test/google.rb, line 35
    def test_atom_google
      xml = "<feed xmlns='http://www.w3.org/2005/Atom'\n    xmlns:gd='http://schemas.google.com/g/2005'>\n  <id>http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full</id>\n  <updated>2006-03-29T07:35:59.000Z</updated>\n  <title type='text'>Jo March</title>\n  <subtitle type='text'>This is my main calendar.</subtitle>\n  <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'\n    href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full'></link>\n  <link rel='self' type='application/atom+xml'\n    href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full'></link>\n  <author>\n    <name>Jo March</name>\n    <email>jo@gmail.com</email>\n  </author>\n  <generator version='1.0' uri='http://www.google.com/calendar/'>CL2</generator>\n  <gd:where valueString='California'></gd:where>\n  <entry>\n    <id>http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID</id>\n    <published>2006-03-30T22:00:00.000Z</published>\n    <updated>2006-03-28T05:47:31.000Z</updated>\n    <category scheme='http://schemas.google.com/g/2005#kind'\n      term='http://schemas.google.com/g/2005#event'></category>\n    <title type='text'>Lunch with Darcy</title>\n    <content type='text'>Lunch to discuss future plans.</content>\n    <link rel='alternate' type='text/html'\n      href='http://www.google.com/calendar/event?eid=aTJxcnNqbW9tcTJnaTE5cnMybmEwaW04bXMgbWFyY2guam9AZ21haWwuY29t'\n      title='alternate'></link>\n    <link rel='self' type='application/atom+xml'\n      href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID'></link>\n    <author>\n      <name>Jo March</name>\n      <email>jo@gmail.com</email>\n    </author>\n    <gd:transparency\n      value='http://schemas.google.com/g/2005#event.opaque'></gd:transparency>\n    <gd:eventStatus\n      value='http://schemas.google.com/g/2005#event.confirmed'></gd:eventStatus>\n    <gd:comments>\n      <gd:feedLink\n        href='http://www.google.com/calendar/feeds/jo@gmail.com/private-magicCookie/full/entryID/comments/'></gd:feedLink>\n    </gd:comments>\n    <gd:when startTime='2006-03-30T22:00:00.000Z'\n      endTime='2006-03-30T23:00:00.000Z'></gd:when>\n    <gd:where></gd:where>\n  </entry>\n</feed>\n"
      f = Syndication::Atom::Parser.new.parse(xml)
      baseline_assertions(f)
      entry = f.entries.first
      assert entry.gd_when[0].to_s == "2006-03-30T22:00:00+00:00"
      assert entry.gd_when[1].to_s == "2006-03-30T23:00:00+00:00"
    end

Minimal test

[Source]

# File test/atomtest.rb, line 35
    def test_atom_minimal
      xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\">\n<title>One good turn usually gets most of the blanket.</title>\n<updated>2005-08-20T21:14:38Z</updated>\n<id>urn:uuid:035d3aa3022c1b1b2a17e37ae2dcc376</id>\n<entry>\n<title>Quidquid latine dictum sit, altum viditur.</title>\n<link href=\"http://example.com/05/08/20/2114.html\"/>\n<id>urn:uuid:89d96d76a99426264f6f1f520c1b93c2</id>\n<updated>2005-08-20T21:14:38Z</updated>\n</entry>\n</feed>\n"
      f = Syndication::Atom::Parser.new.parse(xml)
      baseline_atom_assertions(f)
      assert(f.title.txt == 'One good turn usually gets most of the blanket.')
      assert(f.updated.strftime('%F %T') == '2005-08-20 21:14:38')
      assert(f.entries.length == 1, 'Wrong number of entries in feed')
      assert(f.id == 'urn:uuid:035d3aa3022c1b1b2a17e37ae2dcc376')
      e = f.entries[0]
      assert(e.title.txt == 'Quidquid latine dictum sit, altum viditur.')
      assert(e.links.length == 1, 'Wrong number of links in entry')
      l = e.links[0]
      assert(l.href == 'http://example.com/05/08/20/2114.html')
      assert(e.id == 'urn:uuid:89d96d76a99426264f6f1f520c1b93c2')
      assert(e.updated.strftime('%F %T') == '2005-08-20 21:14:38')
    end

Test a well-formed Atom feed with all possible elements

[Source]

# File test/atomtest.rb, line 67
    def test_atom_wf_full
      xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\">\n<title type=\"text\">It is the quality rather than the quantity that matters.</title>\n<updated>2005-08-20T21:43:44Z</updated>\n<id>urn:uuid:dc03a676cc5f04b9f0c728592270c8b7</id>\n<author>\n<name>mathew</name>\n<email>meta@pobox.com</email>\n<uri>http://www.pobox.com/~meta/</uri>\n</author>\n<category term=\"test\"/>\n<category term=\"Ruby\"/>\n<contributor>\n<name>Phil Space</name>\n<email>space@example.com</email>\n</contributor>\n<contributor>\n<name>Anne Example</name>\n<email>anne@example.com</email>\n</contributor>\n<generator uri=\"http://example.com/ruby/syndication\" version=\"1.0\">\nRuby Syndication Library\n</generator>\n<icon>http://www.example.com/goatseicon.gif</icon>\n<link rel=\"self\" type=\"application/ruby\" href=\"file://atom.rb\"/>\n<logo>http://www.example.com/goatse.jpg</logo>\n<rights>Copyright (c) meta@pobox.com 2005</rights>\n<subtitle type=\"xhtml\">\n<div xmlns=\"http://www.w3.org/1999/xhtml\">\n<p>This is <b>XHTML</b> content.</p>\n</div>\n</subtitle>\n<entry>\n<title>Cleanliness is next to impossible.</title>\n<summary type=\"xhtml\">\n<xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\nThis is <xhtml:b>XHTML</xhtml:b> content.\n</xhtml:div>\n</summary>\n<link href=\"http://example.com/05/08/20/2143.html\"/>\n<id>urn:uuid:380b651e97c2e6ecc68eaa66c90939b6</id>\n<published>1978-03-12T10:22:11Z</published>\n<updated>2005-08-20T21:43:44Z</updated>\n<author>\n<name>Stu Dapples</name>\n<email>stu@example.com</email>\n</author>\n<category term=\"fortune\"/>\n<category term=\"aphorism\"/>\n<content type=\"text\">\nCleanliness of code is certainly next to impossible if you have to parse\nAtom feeds with all their features.\n</content>\n<contributor>\n<name>Ben Dover</name>\n</contributor>\n<contributor>\n<name>Eileen Dover</name>\n</contributor>\n<rights>This test entry is in the public domain.</rights>\n</entry>\n<entry>\n<title type=\"html\">&lt;b>WE HAVE TACOS&lt;/b></title>\n<link href=\"http://www.pobox.com/~meta/\"/>\n<id>urn:uuid:13be6c856fac98d9a7fd144b61dee06d</id>\n<updated>2004-12-23T21:22:23-06:00</updated>\n<source>\n<author><name>Rick O'Shea</name></author>\n<category term=\"example\"/>\n<contributor><name>Hugh Cares</name></contributor>\n<generator uri=\"http://www.pobox.com/~meta/\" version=\"1\">\nTyped in by hand by some poor guy.\n</generator>\n<icon>http://www.example.com/icon2.png</icon>\n<id>urn:uuid:1234decafbad7890deadbeef5678304</id>\n<link rel=\"alternate\" type=\"text/html\"\nhref=\"http://www.pobox.com/~meta/\"/>\n<logo>http://www.example.com/logo.svg</logo>\n<rights>Some rights reserved, some not</rights>\n<title>More example stuff</title>\n<subtitle>MAKE IT STOP!</subtitle>\n<updated>2005-08-20T22:11-05:00</updated>\n</source>\n</entry>\n</feed>\n"
      f = Syndication::Atom::Parser.new.parse(xml)
      baseline_atom_assertions(f)
      assert(f.categories.length == 2)
      assert(f.contributors.length == 2)
      assert(f.contributors[0].name == 'Phil Space', "Feed#contributors name didn't match")
      assert(f.contributors[1].name == 'Anne Example', "Feed#contributors name didn't match")
      assert(f.categories[0].term = 'test', "Feed#categories didn't match")
      assert(f.categories[1].term = 'Ruby', "Feed#categories didn't match")
      assert(f.title.txt == 'It is the quality rather than the quantity that matters.')
      assert(f.updated == DateTime.parse('2005-08-20 21:43:44Z'), 'Feed#updated incorrectly parsed')
      assert(f.author.name == 'mathew')
      assert(f.author.email == 'meta@pobox.com')
      assert(f.author.uri == 'http://www.pobox.com/~meta/')
      assert(f.generator == 'Ruby Syndication Library')
      assert(f.icon == 'http://www.example.com/goatseicon.gif')
      assert(f.links.length == 1)
      assert(f.links[0].rel == 'self')
      assert(f.links[0].href == 'file://atom.rb')
      assert(f.links[0].type == 'application/ruby')
      assert(f.logo == 'http://www.example.com/goatse.jpg')
      assert(f.rights == 'Copyright (c) meta@pobox.com 2005')
      assert(f.subtitle.xhtml == '<p>This is <b>XHTML</b> content.</p>')
      assert(f.entries.length == 2)
      e1 = f.entries[0]
      assert(e1.summary.xhtml == 'This is <b>XHTML</b> content.')
      assert(e1.categories.length == 2)
      assert(e1.categories[0].term == 'fortune')
      assert(e1.categories[1].term == 'aphorism')
      e2 = f.entries[1]
      assert(e2.title.html == '<b>WE HAVE TACOS</b>')
      s = e2.source
      assert(s.kind_of?(Syndication::Atom::Feed))
      assert(s.title.txt == 'More example stuff')
      assert(s.updated == DateTime.parse('2005-08-20 22:11:00-0500'))
    end

[Source]

# File test/feedburntest.rb, line 29
    def test_feedburner
      xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?xml-stylesheet href=\"http://feeds.sfgate.com/~d/styles/rss2full.xsl\" type=\"text/xsl\" media=\"screen\"?>\n<?xml-stylesheet href=\"http://feeds.sfgate.com/~d/styles/itemcontent.css\" type=\"text/css\" media=\"screen\"?>\n<rss xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\" version=\"2.0\">\n<channel>\n<title>SFGate: Top News Stories</title>\n<link>http://www.sfgate.com/</link>\n<description>Top news stories. From SFGate.com: the Bay Area's home page, online home of the San Francisco Chronicle and much more.</description>\n<language>en-us</language>\n<copyright>Copyright 2006 Hearst Communications, Inc.</copyright>\n<managingEditor>ed@sfgate.com (SFGate Editorial staff)</managingEditor>\n<webMaster>support@sfgate.com (SFGate technical support)</webMaster>\n<lastBuildDate>Sun, 09 Jul 2006 14:21:10 PDT</lastBuildDate>\n<category>News</category>\n<category>Newspapers</category>\n<category>San Francisco</category>\n<category>San Francisco Bay Area</category>\n<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n<image>\n<url>http://www.sfgate.com/templates/types/syndication/pages/rss/graphics/sfgate_logo.png</url>\n<title>SFGate: Top News Stories</title>\n<link>http://www.sfgate.com/</link>\n</image>\n<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>\n<item>\n<title><![CDATA[Italy Beats France for 4th World Cup Title]]></title>\n<link>http://feeds.sfgate.com/sfgate/rss/feeds/news?m=4300</link>\n<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>\n<author><![CDATA[By BARRY WILNER, AP Sports Writer]]></author>\n<pubDate>Sun, 09 Jul 2006 14:14:59 PDT</pubDate>\n\n<guid isPermaLink=\"false\">/n/a/2006/07/09/sports/s134544D82.DTL</guid>\n<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>\n</item>\n</channel>\n</rss>\n"
      f = Syndication::RSS::Parser.new.parse(xml)
      il = f.items
      assert_not_nil(il)
      assert(il.length == 1)
      i = il.first
      assert_not_nil(i.feedburner_origlink)
      assert(i.feedburner_origlink == "http://www.sfgate.com/cgi-bin/article.cgi?f=/n/a/2006/07/09/sports/s134544D82.DTL&feed=rss.news")
    end

Test iTunes-specific duration parsing

[Source]

# File test/rsstest.rb, line 311
  def test_itunes
    i = Syndication::RSS::Item.new(nil)
    i.itunes_duration = "12:34:56"
    assert(i.itunes_duration == 45296, "Duration computed incorrectly")
    i.itunes_duration = "5:43:21"
    assert(i.itunes_duration == 20601, "Duration computed incorrectly")
    i.itunes_duration = "20:01"
    assert(i.itunes_duration == 1201, "Duration computed incorrectly")
    i.itunes_duration = "3:52"
    assert(i.itunes_duration == 232, "Duration computed incorrectly")
  end

Test HTML encoded content in RSS 1.0 and namespace remapping

[Source]

# File test/rsstest.rb, line 261
  def test_rss1_content
    xml = "<?xml version=\"1.0\"?>\n<rdf:RDF\nxmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\nxmlns:content=\"http://purl.org/rss/1.0/modules/content/\"\nxmlns=\"http://purl.org/rss/1.0/\">\n<channel rdf:about=\"http://www.otternet.com/\">\n<title>OtterNet</title>\n<link>http://www.otternet.com/</link>\n<description>Otternet has dozens of pages of information about otters.</description>\n<content:encoded><![CDATA[<p><cite>OtterNet</cite> has <em>dozens</em> of pages of information about otters.</p>]]></content:encoded>\n</channel>\n<item rdf:about=\"http://www.otternet.com/species/seaotter.htm\">\n<title>The Sea Otter</title>\n<link>http://www.otternet.com/species/seaotter.htm</link>\n<description>The enticingly cute enhydra lontris.</description>\n<content:encoded>The enticingly cute &lt;i&gt;enhydra lontris&lt;/i&gt;</content:encoded>\n</item>\n<item rdf:about=\"http://www.ruby-lang.org/\">\n<title>Ruby</title>\n<link>http://www.ruby-lang.org/</link>\n<description>There's this language called Ruby, you may have heard of it.</description>\n<content: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.</content:encoded>\n</item>\n</rdf:RDF>\n"
    f = Syndication::RSS::Parser.new.parse(xml)
    baseline_rss_assertions(f)
    il = f.items
    assert(il.length == 2)
    i1 = il.first
    i2 = il.last
    assert_not_nil(i1.content_encoded, "content_encoded nil, shouldn't be")
    assert_not_nil(i2.content_encoded, "content_encoded nil, shouldn't be")
    assert(i1.content_encoded == 'The enticingly cute <i>enhydra lontris</i>')
    assert(i1.content_decoded == 'The enticingly cute <i>enhydra lontris</i>')
    assert(i2.content_decoded == "There's this language called <strong>Ruby</strong>, you <em>may</em> have heard of it.")
    c = f.channel
    assert(c.content_encoded == '<![CDATA[<p><cite>OtterNet</cite> has <em>dozens</em> of pages of information about otters.</p>]]>')
    assert(c.content_decoded == '<p><cite>OtterNet</cite> has <em>dozens</em> of pages of information about otters.</p>')
    assert_not_nil(c)
    assert_kind_of(Syndication::RSS::Channel, c)
    assert_not_nil(c.title)
    assert_not_nil(c.link)
    assert_not_nil(c.description)
  end

Test a well-formed RSS 1.0 feed with every element possible, more than one item, and rdf:resource links in the channel

[Source]

# File test/rsstest.rb, line 195
  def test_rss1_wf_full
    xml = "<rdf:RDF\nxmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\nxmlns=\"http://purl.org/rss/1.0/\">\n<channel>\n<title>Example Dot Org</title>\n<link>http://www.example.org</link>\n<description>the Example Organization web site</description>\n<image rdf:resource=\"http://www.example.org/images/logo.gif\"/>\n<items>\n<rdf:Seq>\n<rdf:li resource=\"http://www.example.org/items/1\"/>\n<rdf:li resource=\"http://www.example.org/items/2\"/>\n</rdf:Seq>\n</items>\n<textinput rdf:resource=\"http://www.example.org/cgi-bin/input.pl\"/>\n</channel>\n<textinput rdf:about=\"http://www.example.org/cgi-bin/input.pl\">\n<title>Search example.org</title>\n<description>Search the example.org web site</description>\n<name>query</name>\n<link>http://www.example.org/cgi-bin/input.pl</link>\n</textinput>\n<image rdf:about=\"http://www.example.org/images/logo.gif\">\n<title>Example.org logo</title>\n<link>http://www.example.org/</link>\n<url>http://www.example.org/images/logo.gif</url>\n</image>\n<item rdf:about=\"http://www.example.org/items/1\">\n<title>Welcome</title>\n<link>http://www.example.org/items/1</link>\n<description>Welcome to our new news feed</description>\n</item>\n<item rdf:about=\"http://www.example.org/items/2\">\n<title>New Status Update</title>\n<link>http://www.example.org/items/1</link>\n<description>News about the Example project</description>\n</item>\n</rdf:RDF>\n"
    f = Syndication::RSS::Parser.new.parse(xml)
    baseline_rss_assertions(f)
    for elem in %w(title link description textinput)
      assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
      assert(f.channel.send(elem).to_s.length > 0)
    end
    il = f.items
    assert(il.length == 2)
    i = il.last
    assert(i.link == 'http://www.example.org/items/1')
    assert(i.title == 'New Status Update')
    assert(i.description == 'News about the Example project')
    assert(f.textinput.title == 'Search example.org')
    f.channel.image.strip
    assert(f.image.url == 'http://www.example.org/images/logo.gif')
    c = f.channel
    assert_not_nil(c)
    assert_kind_of(Syndication::RSS::Channel, c)
    assert_not_nil(c.title)
    assert_not_nil(c.link)
    assert_not_nil(c.description)
  end

Test a minimal well-formed RSS1.0 feed

[Source]

# File test/rsstest.rb, line 60
  def test_rss1_wf_minimal
    xml = "<?xml version=\"1.0\"?>\n<rdf:RDF\nxmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\nxmlns=\"http://purl.org/rss/1.0/\">\n<channel rdf:about=\"http://www.otternet.com/\">\n<title>OtterNet</title>\n<link>http://www.otternet.com/</link>\n<description>Otternet has pages &amp; pages of information about otters.</description>\n</channel>\n<item rdf:about=\"http://www.otternet.com/species/seaotter.htm\">\n<title>The Sea Otter</title>\n<link>http://www.otternet.com/species/seaotter.htm</link>\n<description>The enticingly cute enhydra lontris.</description>\n</item>\n</rdf:RDF>\n"
    f = Syndication::RSS::Parser.new.parse(xml)
    baseline_rss_assertions(f)
    assert(f.channel.title == 'OtterNet')
    assert(f.channel.link == 'http://www.otternet.com/')
    assert(f.channel.description == 'Otternet has pages & pages of information about otters.')
    assert(f.items.first.title == 'The Sea Otter')
    assert(f.items.first.link == 'http://www.otternet.com/species/seaotter.htm')
    assert(f.items.first.description == 'The enticingly cute enhydra lontris.')
    c = f.channel
    assert_not_nil(c)
    assert_kind_of(Syndication::RSS::Channel, c)
    assert_not_nil(c.title)
    assert_not_nil(c.link)
    assert_not_nil(c.description)
  end

Test a well-formed RSS2 feed with every element possible and more than one item

[Source]

# File test/rsstest.rb, line 97
  def test_rss2_wf_full
    xml = "<rss version=\"2\">\n<channel>\n<title>Example Feed</title>\n<link>http://www.example.com/</link>\n<description>This is merely an example.</description>\n<language>en-us</language>\n<copyright>Copyright 2004 The Example Corporation.</copyright>\n<managingEditor>editor@example.com</managingEditor>\n<webMaster>webmaster@example.com</webMaster>\n<pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>\n<lastBuildDate>Sat, 7 Sep 02 13:14:15 -0600</lastBuildDate>\n<category>examples</category>\n<category>boring</category>\n<generator>vim of course</generator>\n<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n<cloud domain=\"rpc.sys.com\" port=\"80\" path=\"/RPC2\" registerProcedure=\"pingMe\" protocol=\"soap\"/>\n<ttl>90</ttl>\n<image>\n<title>Example Inc</title>\n<url>http://www.example.com/images/logo.jpg</url>\n<link>http://www.example.com</link>\n<width>42</width>\n<height>23</height>\n</image>\n<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>\n<textInput>\n<title>Submit</title>\n<description>Enter keywords</description>\n<name>SearchKeywords</name>\n<link>http://www.example.com/cgi-bin/search.pl</link>\n</textInput>\n<skipHours>\n<hour>0</hour>\n<hour>23</hour>\n</skipHours>\n<skipDays>\n<day>Monday</day>\n<day>Sunday</day>\n</skipDays>\n<item>\n<title>Our stock price shot up</title>\n<link>http://www.example.com/news/2.html</link>\n<description>We were hyped in the press!</description>\n</item>\n<item>\n<title>A dull example of little value.</title>\n<link>http://www.example.com/news/1.html</link>\n<description>If this was any less interesting, it would be amazing.</description>\n<author>fred@example.com</author>\n<pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>\n<category>dull</category>\n<category>amazingly</category>\n<comments>http://www.example.com/news/comments/1.html</comments>\n<enclosure url=\"http://www.example.com/mp3/advertisement.mp3\" length=\"123987\" type=\"audio/mpeg\" />\n<guid>4asd98dgf9a74@example.com</guid>\n<source url=\"http://www.example.com/news.xml\">Example News</source>\n</item>\n</channel>\n</rss>\n"
    f = Syndication::RSS::Parser.new.parse(xml)
    baseline_rss_assertions(f)
    for elem in %w(title link description language copyright managingeditor webmaster pubdate lastbuilddate category generator docs cloud ttl textinput rating skiphours skipdays)
      assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
      assert(f.channel.send(elem).to_s.length > 0)
    end
    items = f.items
    assert(items.length == 2)
    i = items.last
    for elem in %w(title link description author pubdate category comments enclosure guid source)
      assert_not_nil(i.send(elem), "feed.channel.item[1].#{elem} is nil, it shouldn't be")
    end
    cats = i.category
    assert(cats.length == 2)
    assert(cats.first == 'dull')
    assert(cats.last == 'amazingly')
    assert(f.channel.skiphours.length == 2)
    assert(f.channel.skiphours.first == 0)
    assert(f.channel.skiphours.last == 23)
    assert(f.channel.pubdate.kind_of?(DateTime))
    assert(f.channel.lastbuilddate.kind_of?(DateTime))
    assert(f.channel.pubdate.mday == 7)
    assert(f.channel.pubdate.month == 9)
    assert(f.channel.lastbuilddate.mday == 7)
    assert(f.channel.lastbuilddate.month == 9)
    c = f.channel
    assert_not_nil(c)
    assert_kind_of(Syndication::RSS::Channel, c)
    assert_not_nil(c.title)
    assert_not_nil(c.link)
    assert_not_nil(c.description)
  end

Test a well-formed RSS2 feed with every element possible and more than one item, with all kinds of stuff CDATA escaped.

[Source]

# File test/rsstest.rb, line 325
  def test_rss2_wf_full_cdata
    xml = "<rss version=\"2\">\n<channel>\n<title><![CDATA[Example Feed]]></title>\n<link>http://www.example.com/</link>\n<description><![CDATA[This is merely an example.]]></description>\n<language>en-us</language>\n<copyright>Copyright 2004 The Example Corporation.</copyright>\n<managingEditor>editor@example.com</managingEditor>\n<webMaster>webmaster@example.com</webMaster>\n<pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>\n<lastBuildDate>Sat, 7 Sep 02 13:14:15 -0600</lastBuildDate>\n<category>examples</category>\n<category>boring</category>\n<generator>vim of course</generator>\n<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n<cloud domain=\"rpc.sys.com\" port=\"80\" path=\"/RPC2\" registerProcedure=\"pingMe\" protocol=\"soap\"/>\n<ttl>90</ttl>\n<image>\n<title><![CDATA[Example Inc]]></title>\n<url>http://www.example.com/images/logo.jpg</url>\n<link>http://www.example.com</link>\n<width>42</width>\n<height>23</height>\n</image>\n<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>\n<textInput>\n<title>Submit</title>\n<description>Enter keywords</description>\n<name>SearchKeywords</name>\n<link>http://www.example.com/cgi-bin/search.pl</link>\n</textInput>\n<skipHours>\n<hour>0</hour>\n<hour>23</hour>\n</skipHours>\n<skipDays>\n<day>Monday</day>\n<day>Sunday</day>\n</skipDays>\n<item>\n<title>Our stock price shot up</title>\n<link>http://www.example.com/news/2.html</link>\n<description>We were hyped in the press!</description>\n</item>\n<item>\n<title><![CDATA[Unencoded < > and & are allowed.]]></title>\n<link><![CDATA[http://www.example.com/news/1.html]]></link>\n<description><![CDATA[If this was any less interesting, it would be amazing.]]></description>\n<author><![CDATA[fred@example.com]]></author>\n<pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>\n<category>dull</category>\n<category>amazingly</category>\n<comments>http://www.example.com/news/comments/1.html</comments>\n<enclosure url=\"http://www.example.com/mp3/advertisement.mp3\" length=\"123987\" type=\"audio/mpeg\" />\n<guid>4asd98dgf9a74@example.com</guid>\n<source url=\"http://www.example.com/news.xml\">Example News</source>\n</item>\n</channel>\n</rss>\n"
    f = Syndication::RSS::Parser.new.parse(xml)
    baseline_rss_assertions(f)
    for elem in %w(title link description language copyright managingeditor webmaster pubdate lastbuilddate category generator docs cloud ttl textinput rating skiphours skipdays)
      assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
      assert(f.channel.send(elem).to_s.length > 0)
    end
    # Check CDATA is decoded properly
    assert(f.channel.title == 'Example Feed')
    assert(f.channel.description == 'This is merely an example.')
    items = f.items
    assert(items.length == 2)
    i = items.last
    for elem in %w(title link description author pubdate category comments enclosure guid source)
      assert_not_nil(i.send(elem), "feed.channel.item[1].#{elem} is nil, it shouldn't be")
    end
    cats = i.category
    assert(i.title == 'Unencoded < > and & are allowed.')
    assert(i.link == 'http://www.example.com/news/1.html')
    assert(cats.length == 2)
    assert(cats.first == 'dull')
    assert(cats.last == 'amazingly')
    assert(f.channel.skiphours.length == 2)
    assert(f.channel.skiphours.first == 0)
    assert(f.channel.skiphours.last == 23)
    assert(f.channel.pubdate.kind_of?(DateTime))
    assert(f.channel.lastbuilddate.kind_of?(DateTime))
    assert(f.channel.pubdate.mday == 7)
    assert(f.channel.pubdate.month == 9)
    assert(f.channel.lastbuilddate.mday == 7)
    assert(f.channel.lastbuilddate.month == 9)
    c = f.channel
    assert_not_nil(c)
    assert_kind_of(Syndication::RSS::Channel, c)
    assert_not_nil(c.title)
    assert_not_nil(c.link)
    assert_not_nil(c.description)
  end

Test a minimal well-formed RSS2.0 feed

[Source]

# File test/rsstest.rb, line 31
  def test_rss2_wf_minimal
    xml = "<rss version=\"2.0\">\n<channel>\n<title>I like coffee</title>\n<link>http://www.coffeegeek.com/</link>\n<description>Hand over the latte &amp; nobody gets hurt.</description>\n</channel>\n<item>\n<description>A day without coffee is incomplete.</description>\n</item>\n</rss>\n"
    f = Syndication::RSS::Parser.new.parse(xml)
    baseline_rss_assertions(f)
    assert(f.channel.title == 'I like coffee')
    assert(f.channel.link == 'http://www.coffeegeek.com/')
    assert(f.channel.description == 'Hand over the latte & nobody gets hurt.')
    assert(f.items.first.description == 'A day without coffee is incomplete.')
    c = f.channel
    assert_not_nil(c)
    assert_kind_of(Syndication::RSS::Channel, c)
    assert_not_nil(c.title)
    assert_not_nil(c.link)
    assert_not_nil(c.description)
  end

Minimal test

[Source]

# File test/tagsouptest.rb, line 40
    def test_tagsoup
      xml = "<a>\n<b>one\n<c></c></b>\n<d arg1=\"alpha\">two</d>\n<e arg2='beta'>\nthree&lt;four&#99;&trade;\n</e>\n</a>\n<feed xmlns=\"http://www.w3.org/2005/Atom\">\n<title>One good turn usually gets most of the blanket.</title>\n<updated>2005-08-20T21:14:38Z</updated>\n<id>urn:uuid:035d3aa3022c1b1b2a17e37ae2dcc376</id>\n<entry>\n<title>Quidquid latine dictum sit, altum viditur.</title>\n<link href=\"http://example.com/05/08/20/2114.html\"/>\n<id>urn:uuid:89d96d76a99426264f6f1f520c1b93c2</id>\n<updated>2005-08-20T21:14:38Z</updated>\n</entry>\n</feed>\n"
      @events = Array.new
      Syndication::TagSoup.parse_stream(xml, self)
      @tagsoup = @events
      @events = Array.new
      REXML::Document.parse_stream(xml, self)
      @rexml = @events
      #puts "REXML\n-----"
      #pp @rexml
      #puts "\nTAGSOUP\n-------"
      #pp @tagsoup
      errs = false
      for tsevt in @tagsoup
        rxevt = @rexml.shift
        if rxevt
          if tsevt.to_s != rxevt.to_s
            errs = true
            #puts "TagSoup: [#{tsevt}]\nREXML: [#{rxevt}]"
          end
        end
      end
      assert(!errs, "TagSoup and REXML parse results didn't match")
    end

[Source]

# File test/tagsouptest.rb, line 35
    def text(x)
      @events << "text(#{x.strip})"
    end

[Validate]