import pytest

from bleach import html5lib_shim


@pytest.mark.parametrize('data, expected', [
    # Strings without character entities pass through as is
    ('', ''),
    ('abc', 'abc'),

    # Handles character entities--both named and numeric
    ('&nbsp;', u'\xa0'),
    ('&#32;', ' '),
    ('&#x20;', ' '),

    # Handles ambiguous ampersand
    ('&xx;', '&xx;'),

    # Handles multiple entities in the same string
    ('this &amp; that &amp; that', 'this & that & that'),
])
def test_convert_entities(data, expected):
    assert html5lib_shim.convert_entities(data) == expected


@pytest.mark.parametrize('data, expected', [
    ('', ''),
    ('text', 'text'),

    # & in Characters is escaped
    ('&', '&amp;'),

    # FIXME(willkg): This happens because the BleachHTMLTokenizer is ignoring
    # character entities. What it should be doing is creating Entity tokens
    # for character entities.
    #
    # That was too hard at the time I was fixing it, so I fixed it in
    # BleachSanitizerFilter. When that gest fixed correctly in the tokenizer,
    # then this test cases will get fixed.
    ('a &amp; b', 'a &amp;amp; b'),    # should be 'a &amp; b'

    # & in HTML attribute values are escaped
    (
        '<a href="http://example.com?key=value&key2=value">tag</a>',
        '<a href="http://example.com?key=value&amp;key2=value">tag</a>'
    ),
    # & marking character entities in HTML attribute values aren't escaped
    (
        '<a href="http://example.com?key=value&amp;key2=value">tag</a>',
        '<a href="http://example.com?key=value&amp;key2=value">tag</a>'
    ),
    # & marking ambiguous character entities in attribute values are escaped
    # (&curren; is a character entity)
    (
        '<a href="http://example.com?key=value&current=value">tag</a>',
        '<a href="http://example.com?key=value&amp;current=value">tag</a>'
    ),

])
def test_serializer(data, expected):
    # Build a parser, walker, and serializer just like we do in clean()
    parser = html5lib_shim.BleachHTMLParser(
        tags=None,
        strip=True,
        consume_entities=False,
        namespaceHTMLElements=False
    )
    walker = html5lib_shim.getTreeWalker('etree')
    serializer = html5lib_shim.BleachHTMLSerializer(
        quote_attr_values='always',
        omit_optional_tags=False,
        escape_lt_in_attrs=True,
        resolve_entities=False,
        sanitize=False,
        alphabetical_attributes=False,
    )

    # Parse, walk, and then serialize the output
    dom = parser.parseFragment(data)
    serialized = serializer.render(walker(dom))

    assert serialized == expected


@pytest.mark.parametrize('parser_args, data, expected', [
    # Make sure InputStreamWithMemory has charEncoding and changeEncoding
    (
        {},
        '<meta charset="utf-8">',
        '<meta charset="utf-8">'
    ),
    # Handle consume entities False--all entities are passed along and then
    # escaped when serialized
    (
        {'consume_entities': False},
        'text &amp;&gt;&quot;',
        'text &amp;amp;&amp;gt;&amp;quot;'
    ),
    # Handle consume entities True--all entities are consumed and converted
    # to their character equivalents and then &, <, and > are escaped when
    # serialized
    (
        {'consume_entities': True},
        'text &amp;&gt;&quot;',
        'text &amp;&gt;"'
    ),
    # Test that "invalid-character-in-attribute-name" errors in tokenizing
    # result in attributes with invalid names getting dropped
    (
        {},
        '<a href="http://example.com"">',
        '<a href="http://example.com"></a>'
    ),
    (
        {},
        '<a href=\'http://example.com\'\'>',
        '<a href="http://example.com"></a>'
    )
])
def test_bleach_html_parser(parser_args, data, expected):
    args = {
        'tags': None,
        'strip': True,
        'consume_entities': True
    }
    args.update(parser_args)

    # Build a parser, walker, and serializer just like we do in clean()
    parser = html5lib_shim.BleachHTMLParser(**args)
    walker = html5lib_shim.getTreeWalker('etree')
    serializer = html5lib_shim.BleachHTMLSerializer(
        quote_attr_values='always',
        omit_optional_tags=False,
        escape_lt_in_attrs=True,
        resolve_entities=False,
        sanitize=False,
        alphabetical_attributes=False,
    )

    # Parse, walk, and then serialize the output
    dom = parser.parseFragment(data)
    serialized = serializer.render(walker(dom))

    assert serialized == expected
