require 'test/unit' require 'happymapper' module OPML class Outline include HappyMapper tag 'outline' attribute :title, String attribute :text, String attribute :type, String attribute :xmlUrl, String attribute :htmlUrl, String has_many :outlines, Outline end class Section include HappyMapper tag 'section' attribute :title, String attribute :text, String has_many :outlines, Outline end end class TestHappyOPML < Test::Unit::TestCase def setup @xml =<<-EOXML mikewoodhouse subscriptions in Google Reader EOXML end def test_as_supplied_by_google_reader sections = OPML::Outline.parse(@xml) # Outline#parse gets all the sections ("outer" outlines) AND all the "inner" outlines too # so we have to delete the inner ones because we want them to be held in the outer ones # as stipulated by the has_many assert_equal 2, sections.size # size is 2 because it parsed both outlines sections.delete_if { |section| section.outlines.size == 0 } assert_equal 1, sections.size # should have removed 1 section = sections.first assert_equal 1, section.outlines.size assert_equal "ruby", section.title assert_equal "ruby", section.text outline = section.outlines.first assert_equal "RailsTips - Home", outline.title assert_equal "RailsTips - Home", outline.text assert_equal "rss", outline.type assert_equal "http://feeds.feedburner.com/railstips", outline.xmlUrl assert_equal "http://railstips.org/", outline.htmlUrl end def test_with_section_outlines_renamed # this is what happens when we (somewhat kludgily) hack the XML to make the # "outer" outlines into "sections"... new_xml = @xml.gsub(/outline title/, 'section title').gsub!(/\/outline/, '/section') # now we can use the Section class: sections = OPML::Section.parse(new_xml) assert_kind_of Array, sections assert_equal 1, sections.size assert_equal 1, sections.first.outlines.size assert_equal "ruby", sections.first.title assert_equal "ruby", sections.first.text end end