1require "rexml/document"
2
3require "rss-testcase"
4
5require "rss/atom"
6
7module RSS
8  class TestAtomCore < TestCase
9    def setup
10      @uri = "http://www.w3.org/2005/Atom"
11      @xhtml_uri = "http://www.w3.org/1999/xhtml"
12    end
13
14    def test_feed
15      version = "1.0"
16      encoding = "UTF-8"
17      standalone = false
18
19      feed = Atom::Feed.new(version, encoding, standalone)
20      assert_equal("", feed.to_s)
21
22      author = feed.class::Author.new
23      name = feed.class::Author::Name.new
24      name.content = "an author"
25      author.name = name
26      assert_not_equal("", author.to_s)
27      feed.authors << author
28      assert_equal("", feed.to_s)
29
30      id = feed.class::Id.new
31      id.content = "http://example.com/atom.xml"
32      assert_not_equal("", id.to_s)
33      feed.id = id
34      assert_equal("", feed.to_s)
35
36      title = feed.class::Title.new
37      title.content = "a title"
38      assert_not_equal("", title.to_s)
39      feed.title = title
40      assert_equal("", feed.to_s)
41
42      updated = feed.class::Updated.new
43      updated.content = Time.now
44      assert_not_equal("", updated.to_s)
45      feed.updated = updated
46      assert_not_equal("", feed.to_s)
47
48
49      feed.authors.clear
50      assert_equal("", feed.to_s)
51      entry = Atom::Feed::Entry.new
52      setup_entry(entry)
53      assert_not_equal("", entry.to_s)
54
55      author = entry.authors.first
56      entry.authors.clear
57      assert_equal("", entry.to_s)
58      entry.parent = feed
59      assert_equal("", entry.to_s)
60      feed.authors << author
61      assert_not_equal("", entry.to_s)
62      feed.authors.clear
63      feed.entries << entry
64      assert_equal("", feed.to_s)
65      entry.authors << author
66      assert_not_equal("", entry.to_s)
67      assert_not_equal("", feed.to_s)
68
69      doc = REXML::Document.new(feed.to_s)
70      xmldecl = doc.xml_decl
71
72      assert_equal(version, xmldecl.version)
73      assert_equal(encoding, xmldecl.encoding.to_s)
74      assert_equal(standalone, !xmldecl.standalone.nil?)
75
76      assert_equal(@uri, doc.root.namespace)
77    end
78
79    def test_entry
80      version = "1.0"
81      encoding = "UTF-8"
82      standalone = false
83
84      entry = Atom::Entry.new(version, encoding, standalone)
85      setup_entry(entry)
86
87      author = entry.authors.first
88      entry.authors.clear
89      assert_equal("", entry.to_s)
90      source = Atom::Entry::Source.new
91      source.authors << author
92      entry.source = source
93      assert_not_equal("", entry.to_s)
94
95      doc = REXML::Document.new(entry.to_s)
96      xmldecl = doc.xml_decl
97
98      assert_equal(version, xmldecl.version)
99      assert_equal(encoding, xmldecl.encoding.to_s)
100      assert_equal(standalone, !xmldecl.standalone.nil?)
101
102      assert_equal(@uri, doc.root.namespace)
103    end
104
105    def test_not_displayed_xml_stylesheets
106      feed = Atom::Feed.new
107      plain_feed = feed.to_s
108      3.times do
109        feed.xml_stylesheets.push(XMLStyleSheet.new)
110        assert_equal(plain_feed, feed.to_s)
111      end
112    end
113
114    def test_atom_author
115      assert_atom_person_to_s(Atom::Feed::Author)
116      assert_atom_person_to_s(Atom::Feed::Entry::Author)
117      assert_atom_person_to_s(Atom::Entry::Author)
118      assert_atom_person_to_s(Atom::Feed::Entry::Source::Author)
119      assert_atom_person_to_s(Atom::Entry::Source::Author)
120    end
121
122    def test_atom_category
123      assert_atom_category_to_s(Atom::Feed::Category)
124      assert_atom_category_to_s(Atom::Feed::Entry::Category)
125      assert_atom_category_to_s(Atom::Entry::Category)
126      assert_atom_category_to_s(Atom::Feed::Entry::Source::Category)
127      assert_atom_category_to_s(Atom::Entry::Source::Category)
128    end
129
130    def test_atom_contributor
131      assert_atom_person_to_s(Atom::Feed::Contributor)
132      assert_atom_person_to_s(Atom::Feed::Entry::Contributor)
133      assert_atom_person_to_s(Atom::Entry::Contributor)
134      assert_atom_person_to_s(Atom::Feed::Entry::Source::Contributor)
135      assert_atom_person_to_s(Atom::Entry::Source::Contributor)
136    end
137
138    def test_atom_generator
139      assert_atom_generator_to_s(Atom::Feed::Generator)
140      assert_atom_generator_to_s(Atom::Feed::Entry::Source::Generator)
141      assert_atom_generator_to_s(Atom::Entry::Source::Generator)
142    end
143
144    def test_atom_icon
145      assert_atom_icon_to_s(Atom::Feed::Icon)
146      assert_atom_icon_to_s(Atom::Feed::Entry::Source::Icon)
147      assert_atom_icon_to_s(Atom::Entry::Source::Icon)
148    end
149
150    def test_atom_id
151      assert_atom_id_to_s(Atom::Feed::Id)
152      assert_atom_id_to_s(Atom::Feed::Entry::Id)
153      assert_atom_id_to_s(Atom::Entry::Id)
154      assert_atom_id_to_s(Atom::Feed::Entry::Source::Id)
155      assert_atom_id_to_s(Atom::Entry::Source::Id)
156    end
157
158    def test_atom_link
159      assert_atom_link_to_s(Atom::Feed::Link)
160      assert_atom_link_to_s(Atom::Feed::Entry::Link)
161      assert_atom_link_to_s(Atom::Entry::Link)
162      assert_atom_link_to_s(Atom::Feed::Entry::Source::Link)
163      assert_atom_link_to_s(Atom::Entry::Source::Link)
164    end
165
166    def test_atom_logo
167      assert_atom_logo_to_s(Atom::Feed::Logo)
168      assert_atom_logo_to_s(Atom::Feed::Entry::Source::Logo)
169      assert_atom_logo_to_s(Atom::Entry::Source::Logo)
170    end
171
172    def test_atom_rights
173      assert_atom_text_construct_to_s(Atom::Feed::Rights)
174      assert_atom_text_construct_to_s(Atom::Feed::Entry::Rights)
175      assert_atom_text_construct_to_s(Atom::Entry::Rights)
176      assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Rights)
177      assert_atom_text_construct_to_s(Atom::Entry::Source::Rights)
178    end
179
180    def test_atom_subtitle
181      assert_atom_text_construct_to_s(Atom::Feed::Subtitle)
182      assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Subtitle)
183      assert_atom_text_construct_to_s(Atom::Entry::Source::Subtitle)
184    end
185
186    def test_atom_title
187      assert_atom_text_construct_to_s(Atom::Feed::Title)
188      assert_atom_text_construct_to_s(Atom::Feed::Entry::Title)
189      assert_atom_text_construct_to_s(Atom::Entry::Title)
190      assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Title)
191      assert_atom_text_construct_to_s(Atom::Entry::Source::Title)
192    end
193
194    def test_atom_updated
195      assert_atom_date_construct_to_s(Atom::Feed::Updated)
196      assert_atom_date_construct_to_s(Atom::Feed::Entry::Updated)
197      assert_atom_date_construct_to_s(Atom::Entry::Updated)
198      assert_atom_date_construct_to_s(Atom::Feed::Entry::Source::Updated)
199      assert_atom_date_construct_to_s(Atom::Entry::Source::Updated)
200    end
201
202    def test_atom_content
203      assert_atom_content_to_s(Atom::Feed::Entry::Content)
204      assert_atom_content_to_s(Atom::Entry::Content)
205    end
206
207    def test_atom_published
208      assert_atom_date_construct_to_s(Atom::Feed::Entry::Published)
209      assert_atom_date_construct_to_s(Atom::Entry::Published)
210    end
211
212    def test_atom_summary
213      assert_atom_text_construct_to_s(Atom::Feed::Entry::Summary)
214      assert_atom_text_construct_to_s(Atom::Entry::Summary)
215    end
216
217
218    def test_to_xml(with_convenience_way=true)
219      atom = RSS::Parser.parse(make_feed)
220      assert_equal(atom.to_s, atom.to_xml)
221      assert_equal(atom.to_s, atom.to_xml("atom"))
222      assert_equal(atom.to_s, atom.to_xml("atom1.0"))
223      assert_equal(atom.to_s, atom.to_xml("atom1.0:feed"))
224      assert_equal(atom.to_s, atom.to_xml("atom:feed"))
225
226      rss09_xml = atom.to_xml("0.91") do |maker|
227        maker.channel.language = "en-us"
228        maker.channel.link = "http://example.com/"
229        if with_convenience_way
230          maker.channel.description = atom.title.content
231        else
232          maker.channel.description {|d| d.content = atom.title.content}
233        end
234
235        maker.image.url = "http://example.com/logo.png"
236        maker.image.title = "Logo"
237      end
238      rss09 = RSS::Parser.parse(rss09_xml)
239      assert_equal(["rss", "0.91", nil], rss09.feed_info)
240
241      rss20_xml = atom.to_xml("2.0") do |maker|
242        maker.channel.link = "http://example.com/"
243        if with_convenience_way
244          maker.channel.description = atom.title.content
245        else
246          maker.channel.description {|d| d.content = atom.title.content}
247        end
248      end
249      rss20 = RSS::Parser.parse(rss20_xml)
250      assert_equal("2.0", rss20.rss_version)
251      assert_equal(["rss", "2.0", nil], rss20.feed_info)
252    end
253
254    def test_to_xml_with_new_api_since_018
255      test_to_xml(false)
256    end
257
258    private
259    def setup_entry(entry)
260      _wrap_assertion do
261        assert_equal("", entry.to_s)
262
263        author = entry.class::Author.new
264        name = entry.class::Author::Name.new
265        name.content = "an author"
266        author.name = name
267        assert_not_equal("", author.to_s)
268        entry.authors << author
269        assert_equal("", entry.to_s)
270
271        id = entry.class::Id.new
272        id.content = "http://example.com/atom.xml"
273        assert_not_equal("", id.to_s)
274        entry.id = id
275        assert_equal("", entry.to_s)
276
277        title = entry.class::Title.new
278        title.content = "a title"
279        assert_not_equal("", title.to_s)
280        entry.title = title
281        assert_equal("", entry.to_s)
282
283        updated = entry.class::Updated.new
284        updated.content = Time.now
285        assert_not_equal("", updated.to_s)
286        entry.updated = updated
287        assert_not_equal("", entry.to_s)
288      end
289    end
290
291
292    def assert_atom_person_to_s(target_class)
293      _wrap_assertion do
294        name = "A person"
295        uri = "http://example.com/person/"
296        email = "person@example.com"
297
298        target = target_class.new
299        assert_equal("", target.to_s)
300
301        target = target_class.new
302        person_name = target_class::Name.new
303        person_name.content = name
304        target.name = person_name
305        xml_target = REXML::Document.new(target.to_s).root
306        assert_equal(["name"], xml_target.elements.collect {|e| e.name})
307        assert_equal([name], xml_target.elements.collect {|e| e.text})
308
309        person_uri = target_class::Uri.new
310        person_uri.content = uri
311        target.uri = person_uri
312        xml_target = REXML::Document.new(target.to_s).root
313        assert_equal(["name", "uri"], xml_target.elements.collect {|e| e.name})
314        assert_equal([name, uri], xml_target.elements.collect {|e| e.text})
315
316        person_email = target_class::Email.new
317        person_email.content = email
318        target.email = person_email
319        xml_target = REXML::Document.new(target.to_s).root
320        assert_equal(["name", "uri", "email"],
321                     xml_target.elements.collect {|e| e.name})
322        assert_equal([name, uri, email],
323                     xml_target.elements.collect {|e| e.text})
324      end
325    end
326
327    def assert_atom_category_to_s(target_class)
328      _wrap_assertion do
329        term = "music"
330        scheme = "http://example.com/music"
331        label = "Music"
332
333        category = target_class.new
334        assert_equal("", category.to_s)
335
336        category = target_class.new
337        category.scheme = scheme
338        assert_equal("", category.to_s)
339
340        category = target_class.new
341        category.label = label
342        assert_equal("", category.to_s)
343
344        category = target_class.new
345        category.scheme = scheme
346        category.label = label
347        assert_equal("", category.to_s)
348
349        category = target_class.new
350        category.term = term
351        xml = REXML::Document.new(category.to_s).root
352        assert_rexml_element([], {"term" => term}, nil, xml)
353
354        category = target_class.new
355        category.term = term
356        category.scheme = scheme
357        xml = REXML::Document.new(category.to_s).root
358        assert_rexml_element([], {"term" => term, "scheme" => scheme}, nil, xml)
359
360        category = target_class.new
361        category.term = term
362        category.label = label
363        xml = REXML::Document.new(category.to_s).root
364        assert_rexml_element([], {"term" => term, "label" => label}, nil, xml)
365
366        category = target_class.new
367        category.term = term
368        category.scheme = scheme
369        category.label = label
370        xml = REXML::Document.new(category.to_s).root
371        attrs = {"term" => term, "scheme" => scheme, "label" => label}
372        assert_rexml_element([], attrs, nil, xml)
373      end
374    end
375
376    def assert_atom_generator_to_s(target_class)
377      _wrap_assertion do
378        content = "Feed generator"
379        uri = "http://example.com/generator"
380        version = "0.0.1"
381
382        generator = target_class.new
383        assert_equal("", generator.to_s)
384
385        generator = target_class.new
386        generator.uri = uri
387        assert_equal("", generator.to_s)
388
389        generator = target_class.new
390        generator.version = version
391        assert_equal("", generator.to_s)
392
393        generator = target_class.new
394        generator.uri = uri
395        generator.version = version
396        assert_equal("", generator.to_s)
397
398        generator = target_class.new
399        generator.content = content
400        xml = REXML::Document.new(generator.to_s).root
401        assert_rexml_element([], {}, content, xml)
402
403        generator = target_class.new
404        generator.content = content
405        generator.uri = uri
406        xml = REXML::Document.new(generator.to_s).root
407        assert_rexml_element([], {"uri" => uri}, content, xml)
408
409        generator = target_class.new
410        generator.content = content
411        generator.version = version
412        xml = REXML::Document.new(generator.to_s).root
413        assert_rexml_element([], {"version" => version}, content, xml)
414
415        generator = target_class.new
416        generator.content = content
417        generator.uri = uri
418        generator.version = version
419        xml = REXML::Document.new(generator.to_s).root
420        assert_rexml_element([], {"uri" => uri, "version" => version},
421                             content, xml)
422      end
423    end
424
425    def assert_atom_icon_to_s(target_class)
426      _wrap_assertion do
427        content = "http://example.com/icon.png"
428
429        icon = target_class.new
430        assert_equal("", icon.to_s)
431
432        icon = target_class.new
433        icon.content = content
434        xml = REXML::Document.new(icon.to_s).root
435        assert_rexml_element([], {}, content, xml)
436      end
437    end
438
439    def assert_atom_id_to_s(target_class)
440      _wrap_assertion do
441        content = "http://example.com/1"
442
443        id = target_class.new
444        assert_equal("", id.to_s)
445
446        id = target_class.new
447        id.content = content
448        xml = REXML::Document.new(id.to_s).root
449        assert_rexml_element([], {}, content, xml)
450      end
451    end
452
453    def assert_atom_link_to_s(target_class)
454      _wrap_assertion do
455        href = "http://example.com/atom.xml"
456        optvs = {
457          'rel' => "self",
458          'type' => "application/atom+xml",
459          'hreflang' => "ja",
460          'title' => "Atom Feed",
461          'length' => "801",
462        }
463
464        link = target_class.new
465        assert_equal("", link.to_s)
466
467        link = target_class.new
468        link.href = href
469        xml = REXML::Document.new(link.to_s).root
470        assert_rexml_element([], {"href" => href}, nil, xml)
471
472        optional_arguments = %w(rel type hreflang title length)
473        optional_arguments.each do |name|
474          rest = optional_arguments.reject {|x| x == name}
475
476          link = target_class.new
477          link.__send__("#{name}=", optvs[name])
478          assert_equal("", link.to_s)
479
480          rest.each do |n|
481            link.__send__("#{n}=", optvs[n])
482            assert_equal("", link.to_s)
483          end
484
485          link = target_class.new
486          link.href = href
487          link.__send__("#{name}=", optvs[name])
488          attrs = [["href", href], [name, optvs[name]]]
489          xml = REXML::Document.new(link.to_s).root
490          assert_rexml_element([], attrs, nil, xml)
491
492          rest.each do |n|
493            link.__send__("#{n}=", optvs[n])
494            attrs << [n, optvs[n]]
495            xml = REXML::Document.new(link.to_s).root
496            assert_rexml_element([], attrs, nil, xml)
497          end
498        end
499      end
500    end
501
502    def assert_atom_logo_to_s(target_class)
503      _wrap_assertion do
504        content = "http://example.com/logo.png"
505
506        logo = target_class.new
507        assert_equal("", logo.to_s)
508
509        logo = target_class.new
510        logo.content = content
511        xml = REXML::Document.new(logo.to_s).root
512        assert_rexml_element([], {}, content, xml)
513      end
514    end
515
516    def assert_atom_text_construct_to_s(target_class)
517      _wrap_assertion do
518        text_content = "plain text"
519        html_content = "<em>#{text_content}</em>"
520        xhtml_uri = "http://www.w3.org/1999/xhtml"
521        xhtml_em = RSS::XML::Element.new("em", nil, xhtml_uri, {}, text_content)
522        xhtml_content = RSS::XML::Element.new("div", nil, xhtml_uri,
523                                              {"xmlns" => xhtml_uri},
524                                              [xhtml_em])
525
526        text = target_class.new
527        assert_equal("", text.to_s)
528
529        text = target_class.new
530        text.type = "text"
531        assert_equal("", text.to_s)
532
533        text = target_class.new
534        text.content = text_content
535        xml = REXML::Document.new(text.to_s).root
536        assert_rexml_element([], {}, text_content, xml)
537
538        text = target_class.new
539        text.type = "text"
540        text.content = text_content
541        xml = REXML::Document.new(text.to_s).root
542        assert_rexml_element([], {"type" => "text"}, text_content, xml)
543
544        text = target_class.new
545        text.type = "html"
546        text.content = html_content
547        xml = REXML::Document.new(text.to_s).root
548        assert_rexml_element([], {"type" => "html"}, html_content, xml)
549
550        text = target_class.new
551        text.type = "xhtml"
552        text.content = xhtml_content
553        assert_equal("", text.to_s)
554
555        text = target_class.new
556        text.type = "xhtml"
557        text.__send__(target_class.xml_setter, xhtml_content)
558        xml = REXML::Document.new(text.to_s).root
559        assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
560                             nil, xml)
561        assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
562        assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
563
564        text = target_class.new
565        text.type = "xhtml"
566        text.__send__(target_class.xml_setter, xhtml_em)
567        xml = REXML::Document.new(text.to_s).root
568        assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
569                             nil, xml)
570        assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
571        assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
572      end
573    end
574
575    def assert_atom_date_construct_to_s(target_class)
576      _wrap_assertion do
577        date = target_class.new
578        assert_equal("", date.to_s)
579
580        [
581         "2003-12-13T18:30:02Z",
582         "2003-12-13T18:30:02.25Z",
583         "2003-12-13T18:30:02+01:00",
584         "2003-12-13T18:30:02.25+01:00",
585        ].each do |content|
586          date = target_class.new
587          date.content = content
588          xml = REXML::Document.new(date.to_s).root
589          assert_rexml_element([], {}, content, xml, :time)
590
591          date = target_class.new
592          date.content = Time.parse(content)
593          xml = REXML::Document.new(date.to_s).root
594          assert_rexml_element([], {}, content, xml, :time)
595        end
596      end
597    end
598
599    def assert_atom_content_to_s(target_class)
600      _wrap_assertion do
601        assert_atom_text_construct_to_s(target_class)
602        assert_atom_content_inline_other_xml_to_s(target_class)
603        assert_atom_content_inline_other_text_to_s(target_class)
604        assert_atom_content_inline_other_base64_to_s(target_class)
605        assert_atom_content_out_of_line_to_s(target_class)
606      end
607    end
608
609    def assert_atom_content_inline_other_xml_to_s(target_class)
610      _wrap_assertion do
611        content = target_class.new
612        content.type = "text/xml"
613        assert_equal("", content.to_s)
614
615        content = target_class.new
616        content.type = "text/xml"
617        content.xml = RSS::XML::Element.new("em")
618        xml = REXML::Document.new(content.to_s).root
619        assert_rexml_element([["", "em"]], {"type" => "text/xml"}, nil, xml)
620      end
621    end
622
623    def assert_atom_content_inline_other_text_to_s(target_class)
624      _wrap_assertion do
625        content = target_class.new
626        content.type = "text/plain"
627        assert_equal("", content.to_s)
628
629        content = target_class.new
630        content.type = "text/plain"
631        content.xml = RSS::XML::Element.new("em")
632        assert_equal("", content.to_s)
633
634        content = target_class.new
635        content.type = "text/plain"
636        content.content = "content"
637        xml = REXML::Document.new(content.to_s).root
638        assert_rexml_element([], {"type" => "text/plain"}, "content", xml)
639      end
640    end
641
642    def assert_atom_content_inline_other_base64_to_s(target_class)
643      _wrap_assertion do
644        type = "image/png"
645        png_file = File.join(File.dirname(__FILE__), "dot.png")
646        original_content = File.open(png_file, "rb") do |file|
647          file.read.force_encoding("binary")
648        end
649
650        content = target_class.new
651        content.type = type
652        content.content = original_content
653        xml = REXML::Document.new(content.to_s).root
654        assert_rexml_element([], {"type" => type},
655                             [original_content].pack("m").delete("\n"),
656                             xml)
657      end
658    end
659
660    def assert_atom_content_out_of_line_to_s(target_class)
661      _wrap_assertion do
662        type = "application/zip"
663        src = "http://example.com/xxx.zip"
664
665        content = target_class.new
666        assert(!content.out_of_line?)
667        content.src = src
668        assert(content.out_of_line?)
669        xml = REXML::Document.new(content.to_s).root
670        assert_rexml_element([], {"src" => src}, nil, xml)
671
672        content = target_class.new
673        assert(!content.out_of_line?)
674        content.type = type
675        assert(!content.out_of_line?)
676        content.src = src
677        assert(content.out_of_line?)
678        xml = REXML::Document.new(content.to_s).root
679        assert_rexml_element([], {"type" => type, "src" => src}, nil, xml)
680      end
681    end
682  end
683end
684