# frozen_string_literal: false require 'erb' module RSS module Assertions def _wrap_assertion yield end def assert_parse(rss, assert_method, *args) __send__("assert_#{assert_method}", *args) do ::RSS::Parser.parse(rss) end __send__("assert_#{assert_method}", *args) do ::RSS::Parser.parse(rss, false).validate end end def assert_ns(prefix, uri) _wrap_assertion do begin yield flunk("Not raise NSError") rescue ::RSS::NSError => e assert_equal(prefix, e.prefix) assert_equal(uri, e.uri) end end end def assert_missing_tag(tag, parent) _wrap_assertion do begin yield flunk("Not raise MissingTagError") rescue ::RSS::MissingTagError => e assert_equal(tag, e.tag) assert_equal(parent, e.parent) end end end def assert_too_much_tag(tag, parent) _wrap_assertion do begin yield flunk("Not raise TooMuchTagError") rescue ::RSS::TooMuchTagError => e assert_equal(tag, e.tag) assert_equal(parent, e.parent) end end end def assert_missing_attribute(tag, attrname) _wrap_assertion do begin yield flunk("Not raise MissingAttributeError") rescue ::RSS::MissingAttributeError => e assert_equal(tag, e.tag) assert_equal(attrname, e.attribute) end end end def assert_not_expected_tag(tag, uri, parent) _wrap_assertion do begin yield flunk("Not raise NotExpectedTagError") rescue ::RSS::NotExpectedTagError => e assert_equal(tag, e.tag) assert_equal(uri, e.uri) assert_equal(parent, e.parent) end end end def assert_not_available_value(tag, value, attribute=nil) _wrap_assertion do begin yield flunk("Not raise NotAvailableValueError") rescue ::RSS::NotAvailableValueError => e assert_equal(tag, e.tag) assert_equal(value, e.value) assert_equal(attribute, e.attribute) end end end def assert_not_set_error(name, variables) _wrap_assertion do begin yield flunk("Not raise NotSetError") rescue ::RSS::NotSetError => e assert_equal(name, e.name) assert_kind_of(Array, variables) assert_equal(variables.sort, e.variables.sort) end end end def assert_xml_declaration(version, encoding, standalone, rss) _wrap_assertion do assert_equal(version, rss.version) assert_equal(encoding, rss.encoding) assert_equal(standalone, rss.standalone) end end def assert_xml_stylesheet_attrs(attrs, xsl) _wrap_assertion do n_attrs = normalized_attrs(attrs) ::RSS::XMLStyleSheet::ATTRIBUTES.each do |name| assert_equal(n_attrs[name], xsl.__send__(name)) end end end def assert_xml_stylesheet(target, attrs, xsl) _wrap_assertion do if attrs.has_key?(:href) if !attrs.has_key?(:type) and attrs.has_key?(:guess_type) attrs[:type] = attrs[:guess_type] end assert_equal("xml-stylesheet", target) assert_xml_stylesheet_attrs(attrs, xsl) else assert_nil(target) assert_equal("", xsl.to_s) end end end def assert_xml_stylesheet_pis(attrs_ary, rss=nil) _wrap_assertion do if rss.nil? rss = ::RSS::RDF.new setup_rss10(rss) end xss_strs = [] attrs_ary.each do |attrs| xss = ::RSS::XMLStyleSheet.new(attrs) xss_strs.push(xss.to_s) rss.xml_stylesheets.push(xss) end pi_str = rss.to_s.gsub(/<\?xml .*\n/, "").gsub(/\s*<[^\?].*\z/m, "") assert_equal(xss_strs.join("\n"), pi_str) end end def assert_xml_stylesheets(attrs, xss) _wrap_assertion do xss.each_with_index do |xs, i| assert_xml_stylesheet_attrs(attrs[i], xs) end end end def assert_atom_person(tag_name, generator) _wrap_assertion do name = "Mark Pilgrim" uri = "http://example.org/" email = "f8dy@example.com" assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name) <#{tag_name}/> EOA assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name) <#{tag_name}> #{uri} #{email} EOA assert_parse(generator.call(<<-EOA), :nothing_raised) <#{tag_name}> #{name} EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) <#{tag_name}> #{name} #{uri} #{email} EOA person = yield(feed) assert_not_nil(person) assert_equal(name, person.name.content) assert_equal(uri, person.uri.content) assert_equal(email, person.email.content) end end def assert_atom_category(generator) _wrap_assertion do term = "Music" scheme = "http://xmlns.com/wordnet/1.6/" label = "music" missing_args = [:missing_attribute, "category", "term"] assert_parse(generator.call(<<-EOA), *missing_args) EOA assert_parse(generator.call(<<-EOA), *missing_args) EOA assert_parse(generator.call(<<-EOA), :nothing_raised) EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) EOA category = yield(feed) assert_not_nil(category) assert_equal(term, category.term) assert_equal(scheme, category.scheme) assert_equal(label, category.label) end end def assert_atom_link(generator) _wrap_assertion do href = "http://example.org/feed.atom" rel = "self" type = "application/atom+xml" hreflang = "en" title = "Atom" length = "1024" assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href") EOA assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href") EOA assert_parse(generator.call(<<-EOA), :nothing_raised) EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) EOA link = yield(feed) assert_not_nil(link) assert_equal(href, link.href) assert_equal(rel, link.rel) assert_equal(type, link.type) assert_equal(hreflang, link.hreflang) assert_equal(title, link.title) assert_equal(length, link.length) href = "http://example.org/index.html.ja" parent = link.parent.tag_name return if parent == "source" optional_attributes = %w(hreflang="ja" type="text/html") 0.upto(optional_attributes.size) do |i| combination(optional_attributes, i).each do |attributes| attrs = attributes.join(" ") assert_parse(generator.call(<<-EOA), :too_much_tag, "link", parent) EOA end end end end def assert_atom_generator(generator) _wrap_assertion do uri = "http://www.example.com/" version = "1.0" content = "Example Toolkit" assert_parse(generator.call(<<-EOA), :nothing_raised) EOA assert_parse(generator.call(<<-EOA), :nothing_raised) EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) #{content} EOA gen = yield(feed) assert_not_nil(gen) assert_equal(uri, gen.uri) assert_equal(version, gen.version) assert_equal(content, gen.content) end end def assert_atom_icon(generator) _wrap_assertion do content = "http://www.example.com/example.png" assert_parse(generator.call(<<-EOA), :nothing_raised) EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) #{content} EOA icon = yield(feed) assert_not_nil(icon) assert_equal(content, icon.content) end end def assert_atom_text_construct(tag_name, generator) _wrap_assertion do [nil, "text", "html"].each do |type| attr = "" attr = " type=\"#{type}\"" if type assert_parse(generator.call(<<-EOA), :nothing_raised) <#{tag_name}#{attr}/> EOA end assert_parse(generator.call(<<-EOA), :missing_tag, "div", tag_name) <#{tag_name} type="xhtml"/> EOA args = ["x", Atom::URI, tag_name] assert_parse(generator.call(<<-EOA), :not_expected_tag, *args) <#{tag_name} type="xhtml"> EOA invalid_value = "invalid" args = ["type", invalid_value] assert_parse(generator.call(<<-EOA), :not_available_value, *args) <#{tag_name} type="#{invalid_value}"/> EOA [ [nil, "A lot of effort went into making this effortless"], ["text", "A lot of effort went into making this effortless"], ["html", "A lot of effort went into making this effortless"], ].each do |type, content| attr = "" attr = " type=\"#{type}\"" if type feed = RSS::Parser.parse(generator.call(<<-EOA)) <#{tag_name}#{attr}>#{h content} EOA element = yield(feed) assert_not_nil(element) assert_equal(type, element.type) assert_equal(content, element.content) end [false, true].each do |with_space| xhtml_uri = "http://www.w3.org/1999/xhtml" xhtml_content = "
abc
" xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri, {"xmlns" => xhtml_uri}, ["abc"]) content = xhtml_content content = " #{content} " if with_space feed = RSS::Parser.parse(generator.call(<<-EOA)) <#{tag_name} type="xhtml">#{content} EOA element = yield(feed) assert_not_nil(element) assert_equal("xhtml", element.type) assert_equal(xhtml_content, element.content) assert_equal(xhtml_element, element.xhtml) end end end def assert_atom_date_construct(tag_name, generator) _wrap_assertion do args = [tag_name, ""] assert_parse(generator.call(<<-EOR), :not_available_value, *args) <#{tag_name}/> EOR [ ["xxx", false], ["2007", false], ["2007/02/09", true], ].each do |invalid_value, can_parse| assert_not_available_value(tag_name, invalid_value) do RSS::Parser.parse(generator.call(<<-EOR)) <#{tag_name}>#{invalid_value} EOR end feed = RSS::Parser.parse(generator.call(<<-EOR), false) <#{tag_name}>#{invalid_value} EOR value = yield(feed).content if can_parse assert_equal(Time.parse(invalid_value), value) else assert_nil(value) end end [ "2003-12-13T18:30:02Z", "2003-12-13T18:30:02.25Z", "2003-12-13T18:30:02+01:00", "2003-12-13T18:30:02.25+01:00", ].each do |valid_value| assert_parse(generator.call(<<-EOR), :nothing_raised) <#{tag_name}>#{valid_value} EOR feed = RSS::Parser.parse(generator.call(<<-EOR)) <#{tag_name}>#{valid_value} EOR assert_equal(Time.parse(valid_value), yield(feed).content) end end end def assert_atom_logo(generator) _wrap_assertion do content = "http://www.example.com/example.png" assert_parse(generator.call(<<-EOA), :nothing_raised) EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) #{content} EOA logo = yield(feed) assert_not_nil(logo) assert_equal(content, logo.content) end end def assert_atom_content(generator, &getter) _wrap_assertion do assert_atom_content_inline_text(generator, &getter) assert_atom_content_inline_xhtml(generator, &getter) assert_atom_content_inline_other(generator, &getter) assert_atom_content_out_of_line(generator, &getter) end end def assert_atom_content_inline_text(generator) _wrap_assertion do [nil, "text", "html"].each do |type| content = "sample content"] ].each do |type, content_content| feed = RSS::Parser.parse(generator.call(<<-EOA)) #{h content_content} EOA content = yield(feed) assert_equal(type, content.type) if %w(text html).include?(type) assert(content.inline_text?) else assert(!content.inline_text?) end if type == "html" assert(content.inline_html?) else assert(!content.inline_html?) end assert(!content.inline_xhtml?) if type == "text/plain" assert(content.inline_other?) assert(content.inline_other_text?) else assert(!content.inline_other?) assert(!content.inline_other_text?) end assert(!content.inline_other_xml?) assert(!content.inline_other_base64?) assert(!content.out_of_line?) assert(!content.have_xml_content?) assert_equal(content_content, content.content) end end end def assert_atom_content_inline_xhtml(generator) _wrap_assertion do args = ["div", "content"] assert_parse(generator.call(<<-EOA), :missing_tag, *args) EOA args = ["x", Atom::URI, "content"] assert_parse(generator.call(<<-EOA), :not_expected_tag, *args) EOA xhtml_uri = "http://www.w3.org/1999/xhtml" xhtml_content = "
abc
" xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri, {"xmlns" => xhtml_uri}, ["abc"]) feed = RSS::Parser.parse(generator.call(<<-EOA)) #{xhtml_content} EOA content = yield(feed) assert_not_nil(content) assert_equal("xhtml", content.type) assert(!content.inline_text?) assert(!content.inline_html?) assert(content.inline_xhtml?) assert(!content.inline_other?) assert(!content.inline_other_text?) assert(!content.inline_other_xml?) assert(!content.inline_other_base64?) assert(!content.out_of_line?) assert(content.have_xml_content?) assert_equal(xhtml_content, content.content) assert_equal(xhtml_element, content.xhtml) end end def assert_atom_content_inline_other(generator, &getter) _wrap_assertion do assert_atom_content_inline_other_text(generator, &getter) assert_atom_content_inline_other_xml(generator, &getter) end end def assert_atom_content_inline_other_text(generator) _wrap_assertion do type = "image/png" assert_parse(generator.call(<<-EOA), :nothing_raised) EOA png_file = File.join(File.dirname(__FILE__), "dot.png") png = File.open(png_file, "rb") do |file| file.read.force_encoding("binary") end base64_content = [png].pack("m").delete("\n") [false, true].each do |with_space| xml_content = base64_content xml_content = " #{base64_content}" if with_space feed = RSS::Parser.parse(generator.call(<<-EOA)) #{xml_content} EOA content = yield(feed) assert_not_nil(content) assert_equal(type, content.type) assert(!content.inline_text?) assert(!content.inline_html?) assert(!content.inline_xhtml?) assert(content.inline_other?) assert(!content.inline_other_text?) assert(!content.inline_other_xml?) assert(content.inline_other_base64?) assert(!content.out_of_line?) assert(!content.have_xml_content?) assert_equal(png, content.content) xml = REXML::Document.new(content.to_s).root assert_rexml_element([], {"type" => type}, base64_content, xml) end end end def assert_atom_content_inline_other_xml(generator) _wrap_assertion do type = "image/svg+xml" assert_parse(generator.call(<<-EOA), :nothing_raised) EOA svg_uri = "http://www.w3.org/2000/svg" svg_width = "50pt" svg_height = "20pt" svg_version = "1.0" text_x = "15" text_y = "15" text = "text" svg_content = <<-EOS #{text} EOS text_element = RSS::XML::Element.new("text", nil, svg_uri, { "x" => text_x, "y" => text_y, }, [text]) svg_element = RSS::XML::Element.new("svg", nil, svg_uri, { "xmlns" => svg_uri, "width" => svg_width, "height" => svg_height, "version" => svg_version, }, [text_element]) feed = RSS::Parser.parse(generator.call(<<-EOA)) #{svg_content} EOA content = yield(feed) assert_not_nil(content) assert_equal(type, content.type) assert(!content.inline_text?) assert(!content.inline_html?) assert(!content.inline_xhtml?) assert(content.inline_other?) assert(!content.inline_other_text?) assert(content.inline_other_xml?) assert(!content.inline_other_base64?) assert(!content.out_of_line?) assert(content.have_xml_content?) assert_equal(REXML::Document.new(svg_content).to_s.chomp, REXML::Document.new(content.content).to_s.chomp) assert_equal(svg_element, content.xml) assert_nil(content.xhtml) end end def assert_atom_content_out_of_line(generator) _wrap_assertion do text_type = "text/plain" text_src = "http://example.com/README.txt" missing_args = [:missing_attribute, "content", "type"] # RSS Parser raises error even if this is "should" not "must". assert_parse(generator.call(<<-EOA), *missing_args) EOA content_content = "xxx" not_available_value_args = [:not_available_value, "content", content_content] assert_parse(generator.call(<<-EOA), *not_available_value_args) #{content_content} EOA feed = RSS::Parser.parse(generator.call(<<-EOA)) EOA content = yield(feed) assert_not_nil(content) assert_equal(text_type, content.type) assert_equal(text_src, content.src) assert(!content.inline_text?) assert(!content.inline_html?) assert(!content.inline_xhtml?) assert(!content.inline_other?) assert(!content.inline_other_text?) assert(!content.inline_other_xml?) assert(!content.inline_other_base64?) assert(content.out_of_line?) assert(!content.have_xml_content?) assert_nil(content.xml) assert_nil(content.xhtml) assert_equal("", content.content) end end def assert_atom_source(generator, &getter) _wrap_assertion do assert_atom_source_author(generator, &getter) assert_atom_source_category(generator, &getter) assert_atom_source_contributor(generator, &getter) assert_atom_source_generator(generator, &getter) assert_atom_source_icon(generator, &getter) assert_atom_source_id(generator, &getter) assert_atom_source_link(generator, &getter) assert_atom_source_logo(generator, &getter) assert_atom_source_rights(generator, &getter) assert_atom_source_subtitle(generator, &getter) assert_atom_source_title(generator, &getter) assert_atom_source_updated(generator, &getter) end end def assert_atom_source_author(generator) assert_atom_person("author", generator) do |feed| source = yield(feed) assert_equal(1, source.authors.size) source.author end end def assert_atom_source_category(generator) assert_atom_category(generator) do |feed| source = yield(feed) assert_equal(1, source.categories.size) source.category end end def assert_atom_source_contributor(generator) assert_atom_person("contributor", generator) do |feed| source = yield(feed) assert_equal(1, source.contributors.size) source.contributor end end def assert_atom_source_generator(generator) assert_atom_generator(generator) do |feed| yield(feed).generator end end def assert_atom_source_icon(generator) assert_atom_icon(generator) do |feed| yield(feed).icon end end def assert_atom_source_id(generator) id_content = "urn:uuid:a2fb588b-5674-4898-b420-265a734fea69" id = "#{id_content}" feed = RSS::Parser.parse(generator.call(id)) assert_equal(id_content, yield(feed).id.content) end def assert_atom_source_link(generator) assert_atom_link(generator) do |feed| source = yield(feed) assert_equal(1, source.links.size) source.link end end def assert_atom_source_logo(generator) assert_atom_logo(generator) do |feed| yield(feed).logo end end def assert_atom_source_rights(generator) assert_atom_text_construct("rights", generator) do |feed| yield(feed).rights end end def assert_atom_source_subtitle(generator) assert_atom_text_construct("subtitle", generator) do |feed| yield(feed).subtitle end end def assert_atom_source_title(generator) assert_atom_text_construct("title", generator) do |feed| yield(feed).title end end def assert_atom_source_updated(generator) assert_atom_date_construct("updated", generator) do |feed| yield(feed).updated end end def assert_dublin_core(elems, target) _wrap_assertion do elems.each do |name, value| assert_equal(value, target.__send__("dc_#{name}")) end end end def assert_multiple_dublin_core(elems, target) _wrap_assertion do elems.each do |name, values, plural| plural ||= "#{name}s" actual = target.__send__("dc_#{plural}").collect{|x| x.value} assert_equal(values, actual) end end end def assert_syndication(elems, target) _wrap_assertion do elems.each do |name, value| meth = "sy_#{name}" value = value.to_i if meth == "sy_updateFrequency" assert_equal(value, target.__send__(meth )) end end end def assert_content(elems, target) _wrap_assertion do elems.each do |name, value| assert_equal(value, target.__send__("content_#{name}")) end end end def assert_trackback(attrs, target) _wrap_assertion do n_attrs = normalized_attrs(attrs) if n_attrs["ping"] assert_equal(n_attrs["ping"], target.trackback_ping) end if n_attrs["abouts"] n_attrs["abouts"].each_with_index do |about, i| assert_equal(about, target.trackback_abouts[i].value) end end end end def assert_taxo_topic(topics, target) _wrap_assertion do topics.each_with_index do |topic, i| taxo_topic = target.taxo_topics[i] topic.each do |name, value| case name when :link assert_equal(value, taxo_topic.about) assert_equal(value, taxo_topic.taxo_link) when :topics assert_equal(value, taxo_topic.taxo_topics.resources) else assert_equal(value, taxo_topic.__send__("dc_#{name}")) end end end end end def assert_attributes(attrs, names, target) _wrap_assertion do n_attrs = normalized_attrs(attrs) names.each do |info| if info.is_a?(String) name = info type = nil else name, type = info end value = n_attrs[name] if value.is_a?(Time) actual = target.__send__(name) assert_instance_of(Time, actual) assert_equal(value.to_i, actual.to_i) elsif value case type when :integer value = value.to_i when :boolean value = value == "true" if value.is_a?(String) end assert_equal(value, target.__send__(name)) end end end end def assert_rexml_element(children, attrs, text, element, text_type=nil) _wrap_assertion do if children children_info = element.elements.collect {|e| [e.namespace, e.name]} assert_equal(children.collect {|uri, name| [uri, name]}.sort, children_info.sort) end if attrs assert_equal(attrs.collect {|k, v| [k, v]}.sort, element.attributes.collect {|k, v| [k, v]}.sort) end case text_type when :time assert_not_nil(element.text) assert_equal(Time.parse(text).to_s, Time.parse(element.text).to_s) else assert_equal(text, element.text) end end end def _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) _wrap_assertion do persons = [] feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker targets = chain_reader(maker, maker_readers) targets.each do |target| person = { :name => target.name, :uri => target.uri, :email => target.email, } persons << person if person[:name] end end actual_persons = chain_reader(feed, feed_readers) || [] actual_persons = actual_persons.collect do |person| { :name => person.name ? person.name.content : nil, :uri => person.uri ? person.uri.content : nil, :email => person.email ? person.email.content : nil, } end assert_equal(persons, actual_persons) end end def assert_maker_atom_persons(feed_type, maker_readers, feed_readers, not_set_error_name=nil, parent_not_set_error_name=nil, parent_not_set_variable=nil) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" args = [feed_type, maker_readers, feed_readers] if parent_not_set_error_name or parent_not_set_variable assert_not_set_error(parent_not_set_error_name, parent_not_set_variable) do _assert_maker_atom_persons(*args) do |maker| yield maker end end else _assert_maker_atom_persons(*args) do |maker| yield maker end end assert_not_set_error(not_set_error_name, %w(name)) do _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) targets.new_child end end assert_not_set_error(not_set_error_name, %w(name)) do _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.uri = "http://example.com/~me/" end end assert_not_set_error(not_set_error_name, %w(name)) do _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.email = "me@example.com" end end assert_not_set_error(not_set_error_name, %w(name)) do _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.uri = "http://example.com/~me/" target.email = "me@example.com" end end _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.name = "me" end _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.name = "me" target.uri = "http://example.com/~me/" end _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.name = "me" target.email = "me@example.com" end _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.name = "me" target.uri = "http://example.com/~me/" target.email = "me@example.com" end _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.name = "me" target.uri = "http://example.com/~me/" target.email = "me@example.com" target = targets.new_child target.name = "you" target.uri = "http://example.com/~you/" target.email = "you@example.com" end assert_not_set_error(not_set_error_name, %w(name)) do _assert_maker_atom_persons(feed_type, maker_readers, feed_readers) do |maker| yield maker targets = chain_reader(maker, maker_readers) target = targets.new_child target.name = "me" target.uri = "http://example.com/~me/" target.email = "me@example.com" targets.new_child end end end end def _assert_maker_atom_text_construct(feed_type, maker_readers, feed_readers, &block) maker_extractor = Proc.new do |target| text = { :type => target.type, :content => target.content, :xml_content => target.xml_content, } if text[:type] == "xhtml" if text[:xml_content] xml_content = text[:xml_content] xhtml_uri = "http://www.w3.org/1999/xhtml" unless xml_content.is_a?(RSS::XML::Element) and ["div", xhtml_uri] == [xml_content.name, xml_content.uri] children = xml_content children = [children] unless children.is_a?(Array) xml_content = RSS::XML::Element.new("div", nil, xhtml_uri, {"xmlns" => xhtml_uri}, children) text[:xml_content] = xml_content end text else nil end else text[:content] ? text : nil end end feed_extractor = Proc.new do |target| { :type => target.type, :content => target.content, :xml_content => target.xhtml, } end _assert_maker_atom_element(feed_type, maker_readers, true, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_text_construct(feed_type, maker_readers, feed_readers, parent_not_set_error_name=nil, parent_not_set_variable=nil, not_set_error_name=nil) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" args = [feed_type, maker_readers, feed_readers] if parent_not_set_error_name or parent_not_set_variable assert_not_set_error(parent_not_set_error_name, parent_not_set_variable) do _assert_maker_atom_text_construct(*args) do |maker| yield maker end end else _assert_maker_atom_text_construct(*args) do |maker| yield maker end end assert_not_set_error(not_set_error_name, %w(content)) do _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "text" end end assert_not_set_error(not_set_error_name, %w(content)) do _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "html" end end assert_not_set_error(not_set_error_name, %w(xml_content)) do _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "xhtml" end end assert_not_set_error(not_set_error_name, %w(xml_content)) do _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "xhtml" target.content = "Content" end end _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "text" target.content = "Content" end _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "html" target.content = "Content" end _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "xhtml" target.xml_content = "text only" end _assert_maker_atom_text_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} target.type = "xhtml" target.xml_content = RSS::XML::Element.new("unknown") end end end def _assert_maker_atom_date_construct(feed_type, maker_readers, feed_readers, &block) maker_extractor = Proc.new do |target| date = { :content => target, } date[:content] ? date : nil end feed_extractor = Proc.new do |target| { :content => target.content, } end _assert_maker_atom_element(feed_type, maker_readers, false, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_date_construct(feed_type, maker_readers, feed_readers, parent_not_set_error_name=nil, parent_not_set_variable=nil) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] if parent_not_set_error_name or parent_not_set_variable assert_not_set_error(parent_not_set_error_name, parent_not_set_variable) do _assert_maker_atom_date_construct(*args) do |maker| yield maker end end else _assert_maker_atom_date_construct(*args) do |maker| yield maker end end maker_readers = maker_readers.dup writer = "#{maker_readers.pop}=" _assert_maker_atom_date_construct(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.__send__(writer, Time.now) end end end def _assert_maker_atom_element(feed_type, maker_readers, maker_readers_need_block, feed_readers, maker_extractor, feed_extractor) _wrap_assertion do element = nil feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker if maker_readers_need_block target = chain_reader(maker, maker_readers) {|x| x} else target = chain_reader(maker, maker_readers) end element = maker_extractor.call(target) end target = chain_reader(feed, feed_readers) if target actual_element = feed_extractor.call(target) else actual_element = nil end assert_equal(element, actual_element) end end def _assert_maker_atom_elements(feed_type, maker_readers, feed_readers, maker_extractor, feed_extractor, invalid_feed_checker=nil) _wrap_assertion do elements = [] invalid_feed_exception = nil feed = nil begin feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker targets = chain_reader(maker, maker_readers) targets.each do |target| element = maker_extractor.call(target) elements << element if element end if invalid_feed_checker invalid_feed_exception = invalid_feed_checker.call(targets) end end rescue RSS::Error if invalid_feed_exception.is_a?(RSS::TooMuchTagError) assert_too_much_tag(invalid_feed_exception.tag, invalid_feed_exception.parent) do raise end else raise end end if invalid_feed_exception.nil? actual_elements = chain_reader(feed, feed_readers) || [] actual_elements = actual_elements.collect do |target| feed_extractor.call(target) end assert_equal(elements, actual_elements) end end end def assert_maker_atom_element(feed_type, maker_readers, feed_readers, setup_target, optional_variables, required_variable, assert_method_name, not_set_error_name=nil, *additional_args) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" 0.upto(optional_variables.size) do |i| combination(optional_variables, i).each do |names| have = {} names.each do |name| have[name.intern] = true end have_required_variable_too = have.merge({required_variable.intern => true}) assert_not_set_error(not_set_error_name, [required_variable]) do __send__(assert_method_name, feed_type, maker_readers, feed_readers, *additional_args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} setup_target.call(target, have) end end __send__(assert_method_name, feed_type, maker_readers, feed_readers, *additional_args) do |maker| yield maker target = chain_reader(maker, maker_readers) {|x| x} setup_target.call(target, have_required_variable_too) end end end end end def assert_maker_atom_elements(feed_type, maker_readers, feed_readers, setup_target, optional_variables, required_variable, assert_method_name, not_set_error_name=nil, *additional_args) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" 0.upto(optional_variables.size) do |i| combination(optional_variables, i).each do |names| have = {} names.each do |name| have[name.intern] = true end have_required_variable_too = have.merge({required_variable.intern => true}) assert_not_set_error(not_set_error_name, [required_variable]) do __send__(assert_method_name, feed_type, maker_readers, feed_readers, *additional_args) do |maker| yield maker targets = chain_reader(maker, maker_readers) setup_target.call(targets, have) end end __send__(assert_method_name, feed_type, maker_readers, feed_readers, *additional_args) do |maker| yield maker targets = chain_reader(maker, maker_readers) setup_target.call(targets, have_required_variable_too) end __send__(assert_method_name, feed_type, maker_readers, feed_readers, *additional_args) do |maker| yield maker targets = chain_reader(maker, maker_readers) setup_target.call(targets, have_required_variable_too) setup_target.call(targets, have_required_variable_too) end assert_not_set_error(not_set_error_name, [required_variable]) do __send__(assert_method_name, feed_type, maker_readers, feed_readers, *additional_args) do |maker| yield maker targets = chain_reader(maker, maker_readers) setup_target.call(targets, have_required_variable_too) setup_target.call(targets, have) end end end end end end def _assert_maker_atom_categories(feed_type, maker_readers, feed_readers, &block) maker_extractor = Proc.new do |target| category = { :term => target.term, :scheme => target.scheme, :label => target.label, } category[:term] ? category : nil end feed_extractor = Proc.new do |target| { :term => target.term, :scheme => target.scheme, :label => target.label, } end _assert_maker_atom_elements(feed_type, maker_readers, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_categories(feed_type, maker_readers, feed_readers, not_set_error_name=nil, &block) _wrap_assertion do _assert_maker_atom_categories(feed_type, maker_readers, feed_readers) do |maker| yield maker end setup_target = Proc.new do |targets, have| target = targets.new_child target.term = "music" if have[:term] target.scheme = "http://example.com/category/music" if have[:scheme] target.label = "Music" if have[:label] end optional_variables = %w(scheme label) assert_maker_atom_elements(feed_type, maker_readers, feed_readers, setup_target, optional_variables, "term", :_assert_maker_atom_categories, not_set_error_name, &block) end end def _assert_maker_atom_generator(feed_type, maker_readers, feed_readers, &block) maker_extractor = Proc.new do |target| generator = { :uri => target.uri, :version => target.version, :content => target.content, } generator[:content] ? generator : nil end feed_extractor = Proc.new do |target| { :uri => target.uri, :version => target.version, :content => target.content, } end _assert_maker_atom_element(feed_type, maker_readers, true, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_generator(feed_type, maker_readers, feed_readers, not_set_error_name=nil, &block) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" _assert_maker_atom_generator(feed_type, maker_readers, feed_readers) do |maker| yield maker end setup_target = Proc.new do |target, have| target.content = "RSS Maker" if have[:content] target.uri = "http://example.com/rss/maker" if have[:uri] target.version = "0.0.1" if have[:version] end optional_variables = %w(uri version) assert_maker_atom_element(feed_type, maker_readers, feed_readers, setup_target, optional_variables, "content", :_assert_maker_atom_generator, not_set_error_name, &block) end end def _assert_maker_atom_icon(feed_type, maker_readers, feed_readers, accessor_base, &block) maker_extractor = Proc.new do |target| icon = { :content => target.__send__(accessor_base), } icon[:content] ? icon : nil end feed_extractor = Proc.new do |target| { :content => target.content, } end _assert_maker_atom_element(feed_type, maker_readers, true, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_icon(feed_type, maker_readers, feed_readers, accessor_base=nil, not_set_error_name=nil) _wrap_assertion do accessor_base ||= "url" not_set_error_name ||= "maker.#{maker_readers.join('.')}" _assert_maker_atom_icon(feed_type, maker_readers, feed_readers, accessor_base) do |maker| yield maker end _assert_maker_atom_icon(feed_type, maker_readers, feed_readers, accessor_base) do |maker| yield maker target = chain_reader(maker, maker_readers) target.__send__("#{accessor_base}=", "http://example.com/icon.png") end end end def _assert_maker_atom_links(feed_type, maker_readers, feed_readers, allow_duplication=false, &block) maker_extractor = Proc.new do |target| link = { :href => target.href, :rel => target.rel, :type => target.type, :hreflang => target.hreflang, :title => target.title, :length => target.length, } link[:href] ? link : nil end feed_extractor = Proc.new do |target| { :href => target.href, :rel => target.rel, :type => target.type, :hreflang => target.hreflang, :title => target.title, :length => target.length, } end if feed_readers.first == "entries" parent = "entry" else parent = feed_type end invalid_feed_checker = Proc.new do |targets| infos = {} invalid_exception = nil targets.each do |target| key = [target.hreflang, target.type] if infos.has_key?(key) invalid_exception = RSS::TooMuchTagError.new("link", parent) break end infos[key] = true if target.rel.nil? or target.rel == "alternate" end invalid_exception end invalid_feed_checker = nil if allow_duplication _assert_maker_atom_elements(feed_type, maker_readers, feed_readers, maker_extractor, feed_extractor, invalid_feed_checker, &block) end def assert_maker_atom_links(feed_type, maker_readers, feed_readers, not_set_error_name=nil, allow_duplication=false, &block) _wrap_assertion do _assert_maker_atom_links(feed_type, maker_readers, feed_readers) do |maker| yield maker end langs = %(ja en fr zh po) setup_target = Proc.new do |targets, have| target = targets.new_child lang = langs[targets.size % langs.size] target.href = "http://example.com/index.html.#{lang}" if have[:href] target.rel = "alternate" if have[:rel] target.type = "text/xhtml" if have[:type] target.hreflang = lang if have[:hreflang] target.title = "FrontPage(#{lang})" if have[:title] target.length = 1024 if have[:length] end optional_variables = %w(rel type hreflang title length) assert_maker_atom_elements(feed_type, maker_readers, feed_readers, setup_target, optional_variables, "href", :_assert_maker_atom_links, not_set_error_name, allow_duplication, &block) end end def _assert_maker_atom_logo(feed_type, maker_readers, feed_readers, accessor_base, &block) maker_extractor = Proc.new do |target| logo = { :uri => target.__send__(accessor_base), } logo[:uri] ? logo : nil end feed_extractor = Proc.new do |target| { :uri => target.content, } end _assert_maker_atom_element(feed_type, maker_readers, true, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_logo(feed_type, maker_readers, feed_readers, accessor_base=nil, not_set_error_name=nil) _wrap_assertion do accessor_base ||= "uri" not_set_error_name ||= "maker.#{maker_readers.join('.')}" _assert_maker_atom_logo(feed_type, maker_readers, feed_readers, accessor_base) do |maker| yield maker end _assert_maker_atom_logo(feed_type, maker_readers, feed_readers, accessor_base) do |maker| yield maker target = chain_reader(maker, maker_readers) target.__send__("#{accessor_base}=", "http://example.com/logo.png") end end end def _assert_maker_atom_id(feed_type, maker_readers, feed_readers, &block) maker_extractor = Proc.new do |target| id = { :uri => target.id, } id[:uri] ? id : nil end feed_extractor = Proc.new do |target| if target.id { :uri => target.id.content, } else nil end end _assert_maker_atom_element(feed_type, maker_readers, true, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_id(feed_type, maker_readers, feed_readers, not_set_error_name=nil) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" args = [feed_type, maker_readers, feed_readers] _assert_maker_atom_id(*args) do |maker| yield maker end _assert_maker_atom_id(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.id = "http://example.com/id/1" end end end def _assert_maker_atom_content(feed_type, maker_readers, feed_readers, &block) maker_extractor = Proc.new do |target| content = { :type => target.type, :src => target.src, :content => target.content, :xml => target.xml, :inline_text => target.inline_text?, :inline_html => target.inline_html?, :inline_xhtml => target.inline_xhtml?, :inline_other => target.inline_other?, :inline_other_text => target.inline_other_text?, :inline_other_xml => target.inline_other_xml?, :inline_other_base64 => target.inline_other_base64?, :out_of_line => target.out_of_line?, } content[:src] = nil if content[:src] and content[:content] if content[:type] or content[:content] content else nil end end feed_extractor = Proc.new do |target| { :type => target.type, :src => target.src, :content => target.content, :xml => target.xml, :inline_text => target.inline_text?, :inline_html => target.inline_html?, :inline_xhtml => target.inline_xhtml?, :inline_other => target.inline_other?, :inline_other_text => target.inline_other_text?, :inline_other_xml => target.inline_other_xml?, :inline_other_base64 => target.inline_other_base64?, :out_of_line => target.out_of_line?, } end _assert_maker_atom_element(feed_type, maker_readers, true, feed_readers, maker_extractor, feed_extractor, &block) end def assert_maker_atom_content(feed_type, maker_readers, feed_readers, not_set_error_name=nil, &block) _wrap_assertion do not_set_error_name ||= "maker.#{maker_readers.join('.')}" args = [feed_type, maker_readers, feed_readers, not_set_error_name] assert_maker_atom_content_inline_text(*args, &block) assert_maker_atom_content_inline_xhtml(*args, &block) assert_maker_atom_content_inline_other(*args, &block) assert_maker_atom_content_out_of_line(*args, &block) end end def assert_maker_atom_content_inline_text(feed_type, maker_readers, feed_readers, not_set_error_name) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] _assert_maker_atom_content(*args) do |maker| yield maker end assert_not_set_error(not_set_error_name, %w(content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "text" end end assert_not_set_error(not_set_error_name, %w(content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "html" end end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.content = "" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "text" target.content = "example content" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "html" target.content = "text" end end end def assert_maker_atom_content_inline_xhtml(feed_type, maker_readers, feed_readers, not_set_error_name) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] assert_not_set_error(not_set_error_name, %w(xml_content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" end end assert_not_set_error(not_set_error_name, %w(xml_content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.content = "dummy" end end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.xml_content = "text" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.xml = "text" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.xml_content = RSS::XML::Element.new("em", nil, nil, {}, ["text"]) end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.xml = RSS::XML::Element.new("em", nil, nil, {}, ["text"]) end xhtml_uri = "http://www.w3.org/1999/xhtml" em = RSS::XML::Element.new("em", nil, nil, {}, ["text"]) em_with_xhtml_uri = RSS::XML::Element.new("em", nil, xhtml_uri, {}, ["text"]) feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.xml = em end assert_equal(RSS::XML::Element.new("div", nil, xhtml_uri, {"xmlns" => xhtml_uri}, [em_with_xhtml_uri]), chain_reader(feed, feed_readers).xml) div = RSS::XML::Element.new("div", nil, xhtml_uri, {"xmlns" => xhtml_uri, "class" => "sample"}, ["text"]) feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "xhtml" target.xml = div end assert_equal(div, chain_reader(feed, feed_readers).xml) end end def assert_maker_atom_content_inline_other(*args, &block) _wrap_assertion do assert_maker_atom_content_inline_other_xml(*args, &block) assert_maker_atom_content_inline_other_text(*args, &block) assert_maker_atom_content_inline_other_base64(*args, &block) end end def assert_maker_atom_content_inline_other_xml(feed_type, maker_readers, feed_readers, not_set_error_name) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] assert_not_set_error(not_set_error_name, %w(xml_content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "application/xml" end end assert_not_set_error(not_set_error_name, %w(xml_content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "svg/image+xml" end end svg_uri = "http://www.w3.org/2000/svg" rect = RSS::XML::Element.new("rect", nil, svg_uri, {"x" => "0.5cm", "y" => "0.5cm", "width" => "2cm", "height" => "1cm"}) svg = RSS::XML::Element.new("svg", nil, svg_uri, {"xmlns" => svg_uri, "version" => "1.1", "width" => "5cm", "height" => "4cm"}, [rect]) _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/svg+xml" target.xml = svg end feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/svg+xml" target.xml = svg end assert_equal(svg, chain_reader(feed, feed_readers).xml) end end def assert_maker_atom_content_inline_other_text(feed_type, maker_readers, feed_readers, not_set_error_name) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] assert_not_set_error(not_set_error_name, %w(content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "text/plain" end end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "text/plain" target.content = "text" end end end def assert_maker_atom_content_inline_other_base64(feed_type, maker_readers, feed_readers, not_set_error_name) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] content = "\211PNG\r\n\032\n" _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/png" target.content = content end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/png" target.src = "http://example.com/logo.png" target.content = content end feed = RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/png" target.src = "http://example.com/logo.png" target.content = content end target = chain_reader(feed, feed_readers) assert_nil(target.src) assert_equal(content, target.content) end end def assert_maker_atom_content_out_of_line(feed_type, maker_readers, feed_readers, not_set_error_name) _wrap_assertion do args = [feed_type, maker_readers, feed_readers] assert_not_set_error(not_set_error_name, %w(content)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/png" end end assert_not_set_error(not_set_error_name, %w(type)) do RSS::Maker.make("atom:#{feed_type}") do |maker| yield maker target = chain_reader(maker, maker_readers) target.src = "http://example.com/logo.png" end end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/png" target.src = "http://example.com/logo.png" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "image/png" target.content = "\211PNG\r\n\032\n" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "application/xml" target.src = "http://example.com/sample.xml" end _assert_maker_atom_content(*args) do |maker| yield maker target = chain_reader(maker, maker_readers) target.type = "text/plain" target.src = "http://example.com/README.txt" end end end def assert_slash_elements(expected, target) assert_equal(expected, { "section" => target.slash_section, "department" => target.slash_department, "comments" => target.slash_comments, "hit_parades" => target.slash_hit_parades, }) assert_equal(expected["hit_parades"].join(","), target.slash_hit_parade) end def chain_reader(target, readers, &block) readers.inject(target) do |result, reader| return nil if result.nil? result.__send__(reader, &block) end end def normalized_attrs(attrs) n_attrs = {} attrs.each do |name, value| n_attrs[name.to_s] = value end n_attrs end def combination(elements, n) if n <= 0 or elements.size < n [] elsif n == 1 elements.collect {|element| [element]} else first, *rest = elements combination(rest, n - 1).collect do |sub_elements| [first, *sub_elements] end + combination(rest, n) end end def tag(name, content=nil, attributes={}) attributes = attributes.collect do |key, value| "#{ERB::Util.h(key)}=\"#{ERB::Util.h(value)}\"" end.join(" ") begin_tag = "<#{name}" begin_tag << " #{attributes}" unless attributes.empty? if content "#{begin_tag}>#{content}\n" else "#{begin_tag}/>\n" end end end end