require 'rdoc/test_case'
class TestRDocMarkupAttributeManager < RDoc::TestCase
  def setup
    super
    @am = RDoc::Markup::AttributeManager.new
    @bold_on  = @am.changed_attribute_by_name([], [:BOLD])
    @bold_off = @am.changed_attribute_by_name([:BOLD], [])
    @tt_on    = @am.changed_attribute_by_name([], [:TT])
    @tt_off   = @am.changed_attribute_by_name([:TT], [])
    @em_on    = @am.changed_attribute_by_name([], [:EM])
    @em_off   = @am.changed_attribute_by_name([:EM], [])
    @bold_em_on   = @am.changed_attribute_by_name([], [:BOLD] | [:EM])
    @bold_em_off  = @am.changed_attribute_by_name([:BOLD] | [:EM], [])
    @em_then_bold = @am.changed_attribute_by_name([:EM], [:EM] | [:BOLD])
    @em_to_bold   = @am.changed_attribute_by_name([:EM], [:BOLD])
    @am.add_word_pair("{", "}", :WOMBAT)
    @wombat_on    = @am.changed_attribute_by_name([], [:WOMBAT])
    @wombat_off   = @am.changed_attribute_by_name([:WOMBAT], [])
    @klass = RDoc::Markup::AttributeManager
    @formatter = RDoc::Markup::Formatter.new @rdoc.options
    @formatter.add_tag :BOLD, '', ''
    @formatter.add_tag :EM, '', ''
    @formatter.add_tag :TT, '', ''
  end
  def crossref(text)
    crossref_bitmap = @am.attributes.bitmap_for(:_SPECIAL_) |
                      @am.attributes.bitmap_for(:CROSSREF)
    [ @am.changed_attribute_by_name([], [:CROSSREF, :_SPECIAL_]),
      RDoc::Markup::Special.new(crossref_bitmap, text),
      @am.changed_attribute_by_name([:CROSSREF, :_SPECIAL_], [])
    ]
  end
  def test_adding
    assert_equal(["cat ", @wombat_on, "and", @wombat_off, " dog" ],
                  @am.flow("cat {and} dog"))
    #assert_equal(["cat {and} dog" ], @am.flow("cat \\{and} dog"))
  end
  def test_add_html_tag
    @am.add_html("Test", :TEST)
    tags = @am.html_tags
    assert_equal(6, tags.size)
    assert(tags.has_key?("test"))
  end
  def test_add_special
    @am.add_special "WikiWord", :WIKIWORD
    specials = @am.special
    assert_equal 1, specials.size
    assert specials.assoc "WikiWord"
  end
  def test_add_word_pair
    @am.add_word_pair '%', '&', 'percent and'
    assert @am.word_pair_map.include?(/(%)(\S+)(&)/)
    assert @am.protectable.include?('%')
    assert !@am.protectable.include?('&')
  end
  def test_add_word_pair_angle
    e = assert_raises ArgumentError do
      @am.add_word_pair '<', '>', 'angles'
    end
    assert_equal "Word flags may not start with '<'", e.message
  end
  def test_add_word_pair_invalid
    assert_raises ArgumentError do
      @am.add_word_pair("<", "<", :TEST)
    end
  end
  def test_add_word_pair_map
    @am.add_word_pair("x", "y", :TEST)
    word_pair_map = @am.word_pair_map
    assert_includes word_pair_map.keys.map { |r| r.source }, "(x)(\\S+)(y)"
  end
  def test_add_word_pair_matching
    @am.add_word_pair '^', '^', 'caret'
    assert @am.matching_word_pairs.include?('^')
    assert @am.protectable.include?('^')
  end
  def test_basic
    assert_equal(["cat"], @am.flow("cat"))
    assert_equal(["cat ", @bold_on, "and", @bold_off, " dog"],
                  @am.flow("cat *and* dog"))
    assert_equal(["cat ", @bold_on, "AND", @bold_off, " dog"],
                  @am.flow("cat *AND* dog"))
    assert_equal(["cat ", @em_on, "And", @em_off, " dog"],
                  @am.flow("cat _And_ dog"))
    assert_equal(["cat *and dog*"], @am.flow("cat *and dog*"))
    assert_equal(["*cat and* dog"], @am.flow("*cat and* dog"))
    assert_equal(["cat *and ", @bold_on, "dog", @bold_off],
                  @am.flow("cat *and *dog*"))
    assert_equal(["cat ", @em_on, "and", @em_off, " dog"],
                  @am.flow("cat _and_ dog"))
    assert_equal(["cat_and_dog"],
                  @am.flow("cat_and_dog"))
    assert_equal(["cat ", @tt_on, "and", @tt_off, " dog"],
                  @am.flow("cat +and+ dog"))
    assert_equal(["cat ", @tt_on, "X::Y", @tt_off, " dog"],
                  @am.flow("cat +X::Y+ dog"))
    assert_equal(["cat ", @bold_on, "a_b_c", @bold_off, " dog"],
                  @am.flow("cat *a_b_c* dog"))
    assert_equal(["cat __ dog"],
                  @am.flow("cat __ dog"))
    assert_equal(["cat ", @em_on, "_", @em_off, " dog"],
                  @am.flow("cat ___ dog"))
  end
  def test_bold
    assert_equal [@bold_on, 'bold', @bold_off],
                 @am.flow("*bold*")
    assert_equal [@bold_on, 'Bold:', @bold_off],
                 @am.flow("*Bold:*")
    assert_equal [@bold_on, '\\bold', @bold_off],
                 @am.flow("*\\bold*")
  end
  def test_bold_html_escaped
    assert_equal ['cat dog'], @am.flow('cat \dog')
  end
  def test_combined
    assert_equal(["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off],
                  @am.flow("cat _and_ *dog*"))
    assert_equal(["cat ", @em_on, "a__nd", @em_off, " ", @bold_on, "dog", @bold_off],
                  @am.flow("cat _a__nd_ *dog*"))
  end
  def test_convert_attrs
    str = '+foo+'
    attrs = RDoc::Markup::AttrSpan.new str.length
    @am.convert_attrs str, attrs
    assert_equal "\000foo\000", str
    str = '+:foo:+'
    attrs = RDoc::Markup::AttrSpan.new str.length
    @am.convert_attrs str, attrs
    assert_equal "\000:foo:\000", str
    str = '+x-y+'
    attrs = RDoc::Markup::AttrSpan.new str.length
    @am.convert_attrs str, attrs
    assert_equal "\000x-y\000", str
  end
  def test_convert_attrs_ignores_code
    assert_equal 'foo __send__ bar', output('foo __send__ bar')
  end
  def test_convert_attrs_ignores_tt
    assert_equal 'foo __send__ bar', output('foo __send__ bar')
  end
  def test_convert_attrs_preserves_double
    assert_equal 'foo.__send__ :bar', output('foo.__send__ :bar')
    assert_equal 'use __FILE__ to', output('use __FILE__ to')
  end
  def test_convert_attrs_does_not_ignore_after_tt
    assert_equal 'the IF:key directive', output('the IF:_key_ directive')
  end
  def test_escapes
    assert_equal 'text',   output('text')
    assert_equal 'text',       output('\\text')
    assert_equal '',                output('\\')
    assert_equal '',   output('\\')
    assert_equal '\\', output('\\\\')
    assert_equal 'text',         output('*text*')
    assert_equal '*text*',              output('\\*text*')
    assert_equal '\\',                  output('\\')
    assert_equal '\\text',              output('\\text')
    assert_equal '\\\\text',            output('\\\\text')
    assert_equal 'text \\ text',        output('text \\ text')
    assert_equal 'and \\s matches space',
                 output('and \\s matches space')
    assert_equal 'use text for code',
                 output('use \\text for code')
    assert_equal 'use text for code',
                 output('use \\text\\ for code')
    assert_equal 'use text for code',
                 output('use \\\\text for code')
    assert_equal 'use text for code',
                 output('use \\text for code')
    assert_equal 'use +text+ for code',
                 output('use \\+text+ for code')
    assert_equal 'use text for code',
                 output('use \\+text+ for code')
    assert_equal 'illegal 
tag
unchanged', output('unhandledtag
unchanged') end def test_html_like_em_bold assert_equal ["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off], @am.flow("cat and dog") end def test_html_like_em_bold_SGML assert_equal ["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off], @am.flow("cat and dog") end def test_html_like_em_bold_nested_1 assert_equal(["cat ", @bold_em_on, "and", @bold_em_off, " dog"], @am.flow("cat and dog")) end def test_html_like_em_bold_nested_2 assert_equal ["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off], @am.flow("cat and dog") end def test_html_like_em_bold_nested_mixed_case assert_equal ["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off], @am.flow("cat and dog") end def test_html_like_em_bold_mixed_case assert_equal ["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off], @am.flow("cat and dog") end def test_html_like_teletype assert_equal ["cat ", @tt_on, "dog", @tt_off], @am.flow("cat dog") end def test_html_like_teletype_em_bold_SGML assert_equal [@tt_on, "cat", @tt_off, " ", @em_on, "and ", @em_to_bold, "dog", @bold_off], @am.flow("cat and dog") end def test_initial_html html_tags = @am.html_tags assert html_tags.is_a?(Hash) assert_equal(5, html_tags.size) end def test_initial_word_pairs word_pairs = @am.matching_word_pairs assert word_pairs.is_a?(Hash) assert_equal(3, word_pairs.size) end def test_mask_protected_sequence def @am.str() @str end def @am.str=(str) @str = str end @am.str = 'foo'
    @am.mask_protected_sequences
    assert_equal "foo",       @am.str
    @am.str = 'foo\\'
    @am.mask_protected_sequences
    assert_equal "foo<\x04/code>", @am.str, 'escaped close'
    @am.str = 'foo\\\\'
    @am.mask_protected_sequences
    assert_equal "foo\\",     @am.str, 'escaped backslash'
  end
  def test_protect
    assert_equal(['cat \\ dog'],
                 @am.flow('cat \\ dog'))
    assert_equal(["cat dog"],
                 @am.flow("cat \\dog"))
    assert_equal(["cat ", @em_on, "and", @em_off, " dog"],
                  @am.flow("cat and \\dog"))
    assert_equal(["*word* or text"],
                 @am.flow("\\*word* or \\text"))
    assert_equal(["_cat_", @em_on, "dog", @em_off],
                  @am.flow("\\_cat_dog"))
  end
  def test_special
    @am.add_special(RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF)
    #
    # The apostrophes in "cats'" and "dogs'" suppress the flagging of these
    # words as potential cross-references, which is necessary for the unit
    # tests.  Unfortunately, the markup engine right now does not actually
    # check whether a cross-reference is valid before flagging it.
    #
    assert_equal(["cats'"], @am.flow("cats'"))
    assert_equal(["cats' ", crossref("#fred"), " dogs'"].flatten,
                  @am.flow("cats' #fred dogs'"))
    assert_equal([crossref("#fred"), " dogs'"].flatten,
                  @am.flow("#fred dogs'"))
    assert_equal(["cats' ", crossref("#fred")].flatten, @am.flow("cats' #fred"))
  end
  def test_tt_html
    assert_equal [@tt_on, '"\n"', @tt_off],
                 @am.flow('"\n"')
  end
  def output str
    @formatter.convert_flow @am.flow str
  end
end