1require "erb" 2 3require "test/unit" 4require 'rss-assertions' 5 6require "rss" 7 8module RSS 9 class TestCase < Test::Unit::TestCase 10 include ERB::Util 11 12 include RSS 13 include Assertions 14 15 XMLDECL_VERSION = "1.0" 16 XMLDECL_ENCODING = "UTF-8" 17 XMLDECL_STANDALONE = "no" 18 19 RDF_ABOUT = "http://www.xml.com/xml/news.rss" 20 RDF_RESOURCE = "http://xml.com/universal/images/xml_tiny.gif" 21 TITLE_VALUE = "XML.com" 22 LINK_VALUE = "http://xml.com/pub" 23 URL_VALUE = "http://xml.com/universal/images/xml_tiny.gif" 24 NAME_VALUE = "hogehoge" 25 LANGUAGE_VALUE = "ja" 26 DESCRIPTION_VALUE = " 27 XML.com features a rich mix of information and services 28 for the XML community. 29 " 30 RESOURCES = [ 31 "http://xml.com/pub/2000/08/09/xslt/xslt.html", 32 "http://xml.com/pub/2000/08/09/rdfdb/index.html", 33 ] 34 35 CLOUD_DOMAIN = "data.ourfavoritesongs.com" 36 CLOUD_PORT = "80" 37 CLOUD_PATH = "/RPC2" 38 CLOUD_REGISTER_PROCEDURE = "ourFavoriteSongs.rssPleaseNotify" 39 CLOUD_PROTOCOL = "xml-rpc" 40 41 ENCLOSURE_URL = "http://www.scripting.com/mp3s/weatherReportSuite.mp3" 42 ENCLOSURE_LENGTH = "12216320" 43 ENCLOSURE_TYPE = "audio/mpeg" 44 45 CATEGORY_DOMAIN = "http://www.superopendirectory.com/" 46 47 FEED_TITLE = "dive into mark" 48 FEED_UPDATED = "2003-12-13T18:30:02Z" 49 FEED_AUTHOR_NAME = "John Doe" 50 FEED_ID = "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6" 51 52 ENTRY_TITLE = "Atom-Powered Robots Run Amok" 53 ENTRY_LINK = "http://example.org/2003/12/13/atom03" 54 ENTRY_ID = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a" 55 ENTRY_UPDATED = "2003-12-13T18:30:02Z" 56 ENTRY_SUMMARY = "Some text." 57 58 t = Time.iso8601("2000-01-01T12:00:05+00:00") 59 class << t 60 alias_method(:to_s, :iso8601) 61 end 62 63 DC_ELEMENTS = { 64 :title => "hoge", 65 :description => 66 " XML is placing increasingly heavy loads on 67 the existing technical infrastructure of the Internet.", 68 :creator => "Rael Dornfest (mailto:rael@oreilly.com)", 69 :subject => "XML", 70 :publisher => "The O'Reilly Network", 71 :contributor => "hogehoge", 72 :type => "fugafuga", 73 :format => "hohoho", 74 :identifier => "fufufu", 75 :source => "barbar", 76 :language => "ja", 77 :relation => "cococo", 78 :rights => "Copyright (c) 2000 O'Reilly & Associates, Inc.", 79 :date => t, 80 } 81 82 DC_NODES = DC_ELEMENTS.collect do |name, value| 83 "<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>" 84 end.join("\n") 85 86 def default_test 87 # This class isn't tested 88 end 89 90 private 91 def make_xmldecl(v=XMLDECL_VERSION, e=XMLDECL_ENCODING, s=XMLDECL_STANDALONE) 92 rv = "<?xml version='#{v}'" 93 rv << " encoding='#{e}'" if e 94 rv << " standalone='#{s}'" if s 95 rv << "?>" 96 rv 97 end 98 99 def make_RDF(content=nil, xmlns=[]) 100 <<-EORSS 101#{make_xmldecl} 102<rdf:RDF xmlns="#{URI}" xmlns:rdf="#{RDF::URI}" 103#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}> 104#{block_given? ? yield : content} 105</rdf:RDF> 106EORSS 107 end 108 109 def make_channel(content=nil) 110 <<-EOC 111<channel rdf:about="#{RDF_ABOUT}"> 112 <title>#{TITLE_VALUE}</title> 113 <link>#{LINK_VALUE}</link> 114 <description>#{DESCRIPTION_VALUE}</description> 115 116 <image rdf:resource="#{RDF_RESOURCE}" /> 117 118 <items> 119 <rdf:Seq> 120#{RESOURCES.collect do |res| '<rdf:li resource="' + res + '" />' end.join("\n")} 121 </rdf:Seq> 122 </items> 123 124 <textinput rdf:resource="#{RDF_RESOURCE}" /> 125 126#{block_given? ? yield : content} 127</channel> 128EOC 129 end 130 131 def make_image(content=nil) 132 <<-EOI 133<image rdf:about="#{RDF_ABOUT}"> 134 <title>#{TITLE_VALUE}</title> 135 <url>#{URL_VALUE}</url> 136 <link>#{LINK_VALUE}</link> 137#{block_given? ? yield : content} 138</image> 139EOI 140 end 141 142 def make_item(content=nil) 143 <<-EOI 144<item rdf:about="#{RDF_ABOUT}"> 145 <title>#{TITLE_VALUE}</title> 146 <link>#{LINK_VALUE}</link> 147 <description>#{DESCRIPTION_VALUE}</description> 148#{block_given? ? yield : content} 149</item> 150EOI 151 end 152 153 def make_textinput(content=nil) 154 <<-EOT 155<textinput rdf:about="#{RDF_ABOUT}"> 156 <title>#{TITLE_VALUE}</title> 157 <description>#{DESCRIPTION_VALUE}</description> 158 <name>#{NAME_VALUE}</name> 159 <link>#{LINK_VALUE}</link> 160#{block_given? ? yield : content} 161</textinput> 162EOT 163 end 164 165 def make_sample_RDF 166 make_RDF(<<-EOR) 167#{make_channel} 168#{make_image} 169#{make_item} 170#{make_textinput} 171EOR 172 end 173 174 def make_rss20(content=nil, xmlns=[]) 175 <<-EORSS 176#{make_xmldecl} 177<rss version="2.0" 178#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}> 179#{block_given? ? yield : content} 180</rss> 181EORSS 182 end 183 184 def make_sample_items20 185 RESOURCES.collect do |res| 186 elems = ["<link>#{res}</link>"] 187 elems << "<title>title of #{res}</title>" 188 elems = elems.join("\n") 189 "<item>\n#{elems}\n</item>" 190 end.join("\n") 191 end 192 193 def make_channel20(content=nil) 194 <<-EOC 195<channel> 196 <title>#{TITLE_VALUE}</title> 197 <link>#{LINK_VALUE}</link> 198 <description>#{DESCRIPTION_VALUE}</description> 199 <language>#{LANGUAGE_VALUE}</language> 200 201 <image> 202 <url>#{RDF_RESOURCE}</url> 203 <title>#{TITLE_VALUE}</title> 204 <link>#{LINK_VALUE}</link> 205 </image> 206 207#{make_sample_items20} 208 209 <textInput> 210 <title>#{TITLE_VALUE}</title> 211 <description>#{DESCRIPTION_VALUE}</description> 212 <name>#{NAME_VALUE}</name> 213 <link>#{RDF_RESOURCE}</link> 214 </textInput> 215 216#{block_given? ? yield : content} 217</channel> 218EOC 219 end 220 221 def make_item20(content=nil) 222 <<-EOI 223<item> 224 <title>#{TITLE_VALUE}</title> 225 <link>#{LINK_VALUE}</link> 226 <description>#{DESCRIPTION_VALUE}</description> 227#{block_given? ? yield : content} 228</item> 229EOI 230 end 231 232 def make_cloud20 233 <<-EOC 234<cloud 235 domain="#{CLOUD_DOMAIN}" 236 port="#{CLOUD_PORT}" 237 path="#{CLOUD_PATH}" 238 registerProcedure="#{CLOUD_REGISTER_PROCEDURE}" 239 protocol="#{CLOUD_PROTOCOL}" /> 240EOC 241 end 242 243 def make_sample_rss20 244 make_rss20(<<-EOR) 245#{make_channel20} 246EOR 247 end 248 249 def make_feed_without_entry(content=nil, xmlns=[]) 250 <<-EOA 251<feed xmlns="#{Atom::URI}" 252#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}> 253 <id>#{FEED_ID}</id> 254 <title>#{FEED_TITLE}</title> 255 <updated>#{FEED_UPDATED}</updated> 256 <author> 257 <name>#{FEED_AUTHOR_NAME}</name> 258 </author> 259#{block_given? ? yield : content} 260</feed> 261EOA 262 end 263 264 def make_entry(content=nil) 265 <<-EOA 266 <entry> 267 <title>#{ENTRY_TITLE}</title> 268 <id>#{ENTRY_ID}</id> 269 <updated>#{ENTRY_UPDATED}</updated> 270#{block_given? ? yield : content} 271 </entry> 272EOA 273 end 274 275 def make_feed_with_open_entry(content=nil, xmlns=[], &block) 276 make_feed_without_entry(<<-EOA, xmlns) 277#{make_entry(content, &block)} 278EOA 279 end 280 281 def make_feed_with_open_entry_source(content=nil, xmlns=[]) 282 make_feed_with_open_entry(<<-EOA, xmlns) 283 <source> 284#{block_given? ? yield : content} 285 </source> 286EOA 287 end 288 289 def make_feed(content=nil, xmlns=[]) 290 make_feed_without_entry(<<-EOA, xmlns) 291 <entry> 292 <title>#{ENTRY_TITLE}</title> 293 <link href="#{ENTRY_LINK}"/> 294 <id>#{ENTRY_ID}</id> 295 <updated>#{ENTRY_UPDATED}</updated> 296 <summary>#{ENTRY_SUMMARY}</summary> 297 </entry> 298#{block_given? ? yield : content} 299EOA 300 end 301 302 def make_entry_document(content=nil, xmlns=[]) 303 <<-EOA 304<entry xmlns="#{Atom::URI}" 305#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}> 306 <id>#{ENTRY_ID}</id> 307 <title>#{ENTRY_TITLE}</title> 308 <updated>#{ENTRY_UPDATED}</updated> 309 <author> 310 <name>#{FEED_AUTHOR_NAME}</name> 311 </author> 312#{block_given? ? yield : content} 313</entry> 314EOA 315 end 316 317 def make_entry_document_with_open_source(content=nil, xmlns=[]) 318 make_entry_document(<<-EOA, xmlns) 319 <source> 320#{block_given? ? yield : content} 321 </source> 322EOA 323 end 324 325 def make_element(elem_name, attrs, contents) 326 attrs_str = attrs.collect do |name, value| 327 "#{h name}='#{h value}'" 328 end.join(" ") 329 attrs_str = " #{attrs_str}" unless attrs_str.empty? 330 331 if contents.is_a?(String) 332 contents_str = h(contents) 333 else 334 contents_str = contents.collect do |name, value| 335 "#{Element::INDENT}<#{h name}>#{h value}</#{h name}>" 336 end.join("\n") 337 contents_str = "\n#{contents_str}\n" 338 end 339 340 "<#{h elem_name}#{attrs_str}>#{contents_str}</#{h elem_name}>" 341 end 342 343 def xmlns_container(xmlns_decls, content) 344 attributes = xmlns_decls.collect do |prefix, uri| 345 "xmlns:#{h prefix}=\"#{h uri}\"" 346 end.join(" ") 347 "<dummy #{attributes}>#{content}</dummy>" 348 end 349 350 private 351 def setup_rss10(rdf) 352 assert_equal("", rdf.to_s) 353 354 channel = RDF::Channel.new 355 assert_equal("", channel.to_s) 356 channel.about = "http://example.com/index.rdf" 357 channel.title = "title" 358 channel.link = "http://example.com/" 359 channel.description = "description" 360 assert_equal("", channel.to_s) 361 362 item_title = "item title" 363 item_link = "http://example.com/item" 364 channel.items = RDF::Channel::Items.new 365 channel.items.Seq.lis << RDF::Channel::Items::Seq::Li.new(item_link) 366 assert_not_equal("", channel.to_s) 367 368 rdf.channel = channel 369 assert_equal("", rdf.to_s) 370 371 item = RDF::Item.new 372 item.title = item_title 373 item.link = item_link 374 item.about = item_link 375 rdf.items << item 376 assert_not_equal("", rdf.to_s) 377 end 378 379 def setup_rss20(rss) 380 assert_equal("", rss.to_s) 381 382 channel = Rss::Channel.new 383 assert_equal("", channel.to_s) 384 channel.title = "title" 385 channel.link = "http://example.com/" 386 channel.description = "description" 387 assert_not_equal("", channel.to_s) 388 389 rss.channel = channel 390 assert_not_equal("", rss.to_s) 391 end 392 393 def setup_dummy_channel(maker) 394 about = "http://hoge.com" 395 title = "fugafuga" 396 link = "http://hoge.com/feed.xml" 397 description = "fugafugafugafuga" 398 language = "ja" 399 400 maker.channel.about = about 401 maker.channel.title = title 402 maker.channel.link = link 403 maker.channel.description = description 404 maker.channel.language = language 405 end 406 407 def setup_dummy_channel_atom(maker) 408 updated = Time.now 409 author = "Foo" 410 411 setup_dummy_channel(maker) 412 maker.channel.links.first.rel = "self" 413 maker.channel.links.first.type = "application/atom+xml" 414 maker.channel.updated = updated 415 maker.channel.author = author 416 end 417 418 def setup_dummy_image(maker) 419 title = "fugafuga" 420 link = "http://hoge.com" 421 url = "http://hoge.com/hoge.png" 422 423 maker.channel.link = link if maker.channel.link.nil? 424 425 maker.image.title = title 426 maker.image.url = url 427 end 428 429 def setup_dummy_textinput(maker) 430 title = "fugafuga" 431 description = "text hoge fuga" 432 name = "hoge" 433 link = "http://hoge.com/search.cgi" 434 435 maker.textinput.title = title 436 maker.textinput.description = description 437 maker.textinput.name = name 438 maker.textinput.link = link 439 end 440 441 def setup_dummy_item(maker) 442 title = "TITLE" 443 link = "http://hoge.com/" 444 445 item = maker.items.new_item 446 item.title = title 447 item.link = link 448 end 449 450 def setup_dummy_item_atom(maker) 451 setup_dummy_item(maker) 452 453 item = maker.items.first 454 item.id = "http://example.net/xxx" 455 item.updated = Time.now 456 end 457 458 def setup_taxo_topic(target, topics) 459 topics.each do |topic| 460 taxo_topic = target.taxo_topics.new_taxo_topic 461 topic.each do |name, value| 462 case name 463 when :link 464 taxo_topic.taxo_link = value 465 when :topics 466 value.each do |t| 467 taxo_topic.taxo_topics << t 468 end 469 else 470 dc_elems = taxo_topic.__send__("dc_#{name}s") 471 dc_elem = dc_elems.__send__("new_#{name}") 472 dc_elem.value = value 473 end 474 end 475 end 476 end 477 end 478end 479