Esempio n. 1
0
def test_Arguments_keys():
    positional = ['positional', 'both']
    keyword = {'keyword': True, 'both': False}

    a = Arguments(positional, keyword)

    args = list(a.keys())

    assert len(args) == 2
    assert 'keyword' in args
    assert 'both' in args
Esempio n. 2
0
def test_Arguments_values():
    positional = ['positional', 'both']
    keyword = {'keyword': True, 'both': False}

    a = Arguments(positional, keyword)

    args = list(a.values())

    assert len(args) == 4
    assert args[0] == 'positional'
    assert args[1] == 'both'
    assert True in args
    assert False in args
Esempio n. 3
0
def test_Arguments_items():
    positional = ['positional', 'both']
    keyword = {'keyword': True, 'both': False}

    a = Arguments(positional, keyword)

    args = list(a.items())

    assert len(args) == 4
    assert args[0] == (None, 'positional')
    assert args[1] == (None, 'both')
    assert ('keyword', True) in args
    assert ('both', False) in args
Esempio n. 4
0
def test_Macro():
    """ test for Macro.macros """
    macro_obj = Macro()
    arguments = Arguments(['test_argument1 test_argument2'])
    result = macro_obj.macro('content', arguments, 'page_url', 'alternative')
    expected = 'test_argument1 test_argument2'
    assert result == expected
Esempio n. 5
0
def test_Arguments___len__():
    positional = ['positional', 'both']
    keyword = {'keyword': None, 'both': None}

    a = Arguments(positional, keyword)

    assert len(a) == 4
Esempio n. 6
0
def test_Arguments___contains__():
    positional = ['positional', 'both']
    keyword = {'keyword': None, 'both': None}

    a = Arguments(positional, keyword)

    assert 'positional' in a
    assert 'keyword' in a
    assert 'both' in a
    assert 'none' not in a
Esempio n. 7
0
def test_Arguments___init__():
    positional = []
    keyword = {}

    a = Arguments(positional, keyword)

    assert positional == a.positional
    assert positional is not a.positional
    assert keyword == a.keyword
    assert keyword is not a.keyword
Esempio n. 8
0
def test_Arguments___getitem__():
    positional = ['positional', 'both']
    keyword = {'keyword': None, 'both': None}

    a = Arguments(positional, keyword)

    assert a[0] == 'positional'
    assert a[1] == 'both'
    assert a[:] == positional
    assert a['keyword'] is None
    assert a['both'] is None

    pytest.raises(IndexError, a.__getitem__, 2)
    pytest.raises(KeyError, a.__getitem__, 'none')
Esempio n. 9
0
class TestConverter:
    namespaces = {
        moin_page.namespace: '',
        xinclude.namespace: 'xi',
        xlink.namespace: 'xlink',
    }

    output_re = XMLNS_RE2

    def setup_class(self):
        self.conv = ConverterMacro()

    data = [
        ('Macro', None, 'text',
         '<part alt="text" content-type="x-moin/macro;name=Macro" />',
         '<inline-part alt="text" content-type="x-moin/macro;name=Macro" />'),
        ('Macro', 'arg1', 'text',
         '<part alt="text" content-type="x-moin/macro;name=Macro"><arguments>arg1</arguments></part>',
         '<inline-part alt="text" content-type="x-moin/macro;name=Macro"><arguments>arg1</arguments></inline-part>'
         ),
    ]

    @pytest.mark.parametrize('name,args,text,output_block,output_inline', data)
    def test_macro(self, name, args, text, output_block, output_inline):
        self._do(name, args, text, True, output_block)
        self._do(name, args, text, False, output_inline)

    data = [
        ('Macro', None, 'text',
         '<inline-part alt="text" content-type="x-moin/macro;name=Macro" />'),
        ('Macro', 'arg1,arg2', 'text',
         '<inline-part alt="text" content-type="x-moin/macro;name=Macro"><arguments>arg1,arg2</arguments></inline-part>'
         ),
        ('Macro', 'key=value', 'text',
         '<inline-part alt="text" content-type="x-moin/macro;name=Macro"><arguments>key=value</arguments></inline-part>'
         ),
        ('Macro', 'arg1,arg2,key=value', 'text',
         '<inline-part alt="text" content-type="x-moin/macro;name=Macro"><arguments>arg1,arg2,key=value</arguments></inline-part>'
         ),
    ]

    @pytest.mark.parametrize('name,args,text,output', data)
    def test_macro_arguments(self, name, args, text, output):
        self._do(name, args, text, False, output)

    data = [
        ('BR', None, 'text', None, '<line-break />'),
        ('FootNote', 'note', 'text',
         '<p><note note-class="footnote"><note-body>note</note-body></note></p>',
         '<note note-class="footnote"><note-body>note</note-body></note>'),
        ('TableOfContents', None, 'text', '<table-of-content />', 'text'),
        ('Include', 'page', 'text',
         '<div class="moin-p"><xi:include xi:href="wiki.local:page" /></div>',
         '<xi:include xi:href="wiki.local:page" />'),
        ('Include', '^page', 'text',
         '<div class="moin-p"><xi:include xi:xpointer="page:include(pages(^^page))" /></div>',
         '<xi:include xi:xpointer="page:include(pages(^^page))" />'),
        # each Include macro performs its own parsing as needed
        ('Include', '^page, sort=ascending', 'text',
         '<div class="moin-p"><xi:include xi:xpointer="page:include(pages(^^page) sort(ascending))" /></div>',
         '<xi:include xi:xpointer="page:include(pages(^^page) sort(ascending))" />'
         ),
        ('Include', '^page, sort=descending', 'text',
         '<div class="moin-p"><xi:include xi:xpointer="page:include(pages(^^page) sort(descending))" /></div>',
         '<xi:include xi:xpointer="page:include(pages(^^page) sort(descending))" />'
         ),
        ('Include', '^page, items=5', 'text',
         '<div class="moin-p"><xi:include xi:xpointer="page:include(pages(^^page) items(5))" /></div>',
         '<xi:include xi:xpointer="page:include(pages(^^page) items(5))" />'),
        ('Include', '^page, skipitems=5', 'text',
         '<div class="moin-p"><xi:include xi:xpointer="page:include(pages(^^page) skipitems(5))" /></div>',
         '<xi:include xi:xpointer="page:include(pages(^^page) skipitems(5))" />'
         ),
    ]

    @pytest.mark.parametrize('name,args,text,output_block,output_inline', data)
    def test_pseudomacro(self, name, args, text, output_block, output_inline):
        self._do(name, args, text, True, output_block)
        self._do(name, args, text, False, output_inline)

    data = [
        ('test', None, ('text', ),
         '<part content-type="x-moin/format;name=test"><body>text</body></part>'
         ),
        # this form works, but is no longer used
        ('test', Arguments(['arg1']), ('text', ),
         '<part content-type="x-moin/format;name=test"><arguments><argument>arg1</argument></arguments><body>text</body></part>'
         ),
    ]

    @pytest.mark.parametrize('name,args,text,output', data)
    def test_parser(self, name, args, text, output):
        self._do_parser(name, args, text, output)

    def serialize_strip(self, elem, **options):
        result = serialize(elem, namespaces=self.namespaces, **options)
        return self.output_re.sub('', result)

    def _do(self, name, args, text, context_block, output):
        result = self.conv.macro(name, args, text, context_block)
        if output is not None or result is not None:
            if not isinstance(result, str):
                result = self.serialize_strip(result)
            assert result == output

    def _do_parser(self, name, args, text, output):
        result = self.conv.parser(name, args, text)
        if output is not None or result is not None:
            result = self.serialize_strip(result)
            assert result == output
Esempio n. 10
0
class TestConverter:
    namespaces = {
        moin_page: '',
        xlink: 'xlink',
        html: 'xhtml',
        xinclude: 'xinclude',
    }

    output_re = XMLNS_RE

    def setup_class(self):
        self.conv = Converter()

    data = [
        ('Text', '<page><body><p>Text</p></body></page>'),
        ('Text\nTest', '<page><body><p>Text\nTest</p></body></page>'),
        ('Text\n\nTest', '<page><body><p>Text</p><p>Test</p></body></page>'),
        ('[[http://moinmo.in/]]',
         '<page><body><p><a xlink:href="http://moinmo.in/">http://moinmo.in/</a></p></body></page>'
         ),
        ('[[javascript:alert("xss")]]',
         '<page><body><p><a xlink:href="wiki.local:javascript:alert%28%22xss%22%29">javascript:alert("xss")</a></p></body></page>'
         ),
        ('[[http://moinmo.in/|MoinMoin]]',
         '<page><body><p><a xlink:href="http://moinmo.in/">MoinMoin</a></p></body></page>'
         ),
        ('[[MoinMoin]]',
         '<page><body><p><a xlink:href="wiki.local:MoinMoin">MoinMoin</a></p></body></page>'
         ),
        ('[[MoinMoin#Heading]]',
         '<page><body><p><a xlink:href="wiki.local:MoinMoin#Heading">MoinMoin</a></p></body></page>'
         ),
        ('[[#Heading]]',
         '<page><body><p><a xlink:href="wiki.local:#Heading"></a></p></body></page>'
         ),
        ('[[/inner2.png|{{/inner2.png||width=500}}]]',
         '<page><body><p><a xlink:href="wiki.local:/inner2.png"><xinclude:include xhtml:width="500" xinclude:href="wiki.local:/inner2.png?" /></a></p></body></page>'
         ),
        ('{{somelocalimage|my alt text|width=10, height=10}}',
         '<page><body><p><xinclude:include xhtml:alt="my alt text" xhtml:height="10" xhtml:width="10" xinclude:href="wiki.local:somelocalimage?" /></p></body></page>'
         ),
        # html5 requires img tags to have an alt attribute, html_out.py will add any required attributes that are missing
        ('{{somelocalimage||width=10, height=10}}',
         '<page><body><p><xinclude:include xhtml:height="10" xhtml:width="10" xinclude:href="wiki.local:somelocalimage?" /></p></body></page>'
         ),
        ('{{somelocalimage||width=10, &h=10}}',
         '<page><body><p><xinclude:include xhtml:width="10" xinclude:href="wiki.local:somelocalimage?h=10" /></p></body></page>'
         ),
        ('before {{somelocalimage}} middle {{somelocalimage}} after',
         '<page><body><p>before <xinclude:include xinclude:href="wiki.local:somelocalimage?" /> middle <xinclude:include xinclude:href="wiki.local:somelocalimage?" /> after</p></body></page>'
         ),
        ('before {{http://moinmo.in}} middle {{http://moinmo.in}} after',
         '<page><body><p>before <object xlink:href="http://moinmo.in" /> middle <object xlink:href="http://moinmo.in" /> after</p></body></page>'
         ),
        # in html5, object tags must not have alt attributes, html_out.py will adjust this so alt text is placed before the </object>
        ('{{http://moinmo.in/|test|width=10, height=10}}',
         '<page><body><p><object xhtml:alt="test" xhtml:height="10" xhtml:width="10" xlink:href="http://moinmo.in/" /></p></body></page>'
         ),
        ('{{http://moinmo.in/}}',
         '<page><body><p><object xlink:href="http://moinmo.in/" /></p></body></page>'
         ),
        ('{{http://moinmo.in/|MoinMoin}}',
         '<page><body><p><object xhtml:alt="MoinMoin" xlink:href="http://moinmo.in/" /></p></body></page>'
         ),
        ('----', '<page><body><separator class="moin-hr1" /></body></page>'),
    ]

    @pytest.mark.parametrize('args', data)
    def test_base(self, args):
        self.do(*args)

    data = [
        ('Text',
         '<page><body style="background-color: red"><p>Text</p></body></page>',
         {
             'arguments': Arguments(keyword={'style': 'background-color: red'})
         }),
    ]

    @pytest.mark.parametrize('input,output,args', data)
    def test_args(self, input, output, args):
        self.do(input, output, args)

    data = [
        ("''Emphasis''",
         '<page><body><p><emphasis>Emphasis</emphasis></p></body></page>'),
        ("'''Strong'''",
         '<page><body><p><strong>Strong</strong></p></body></page>'),
        ("'''''Both'''''",
         '<page><body><p><strong><emphasis>Both</emphasis></strong></p></body></page>'
         ),
        ("'''''Mixed'''Emphasis''",
         '<page><body><p><emphasis><strong>Mixed</strong>Emphasis</emphasis></p></body></page>'
         ),
        ("'''''Mixed''Strong'''",
         '<page><body><p><strong><emphasis>Mixed</emphasis>Strong</strong></p></body></page>'
         ),
        ("Text ''Emphasis\n''Text",
         '<page><body><p>Text <emphasis>Emphasis\n</emphasis>Text</p></body></page>'
         ),
        ("Text ''Emphasis\n\nText",
         '<page><body><p>Text <emphasis>Emphasis</emphasis></p><p>Text</p></body></page>'
         ),
        ("Text''''''Text''''", '<page><body><p>TextText</p></body></page>'),
        ("''italic '''strongitalic ''''' normal",
         '<page><body><p><emphasis>italic <strong>strongitalic </strong></emphasis> normal</p></body></page>'
         ),
        ("'''strong '''''italic '''strongitalic''''' normal",
         '<page><body><p><strong>strong </strong><emphasis>italic <strong>strongitalic</strong></emphasis> normal</p></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_emphasis(self, input, output):
        self.do(input, output)

    data = [
        (
            '=Not_a_Heading=',  # this is for better moin 1.x compatibility
            '<page><body><p>=Not_a_Heading=</p></body></page>'),
        ('= Heading 1 =',
         '<page><body><h outline-level="1">Heading 1</h></body></page>'),
        ('== Heading 2 ==',
         '<page><body><h outline-level="2">Heading 2</h></body></page>'),
        ('=== Heading 3 ===',
         '<page><body><h outline-level="3">Heading 3</h></body></page>'),
        ('==== Heading 4 ====',
         '<page><body><h outline-level="4">Heading 4</h></body></page>'),
        ('===== Heading 5 =====',
         '<page><body><h outline-level="5">Heading 5</h></body></page>'),
        ('====== Heading 6 ======',
         '<page><body><h outline-level="6">Heading 6</h></body></page>'),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_heading(self, input, output):
        self.do(input, output)

    data = [
        ("__underline__",
         '<page><body><p><ins>underline</ins></p></body></page>'),
        (",,sub,,script",
         '<page><body><p><span baseline-shift="sub">sub</span>script</p></body></page>'
         ),
        ("^super^script",
         '<page><body><p><span baseline-shift="super">super</span>script</p></body></page>'
         ),
        ("~-smaller-~",
         '<page><body><p><span font-size="85%">smaller</span></p></body></page>'
         ),
        ("~+larger+~",
         '<page><body><p><span font-size="120%">larger</span></p></body></page>'
         ),
        ("--(strike through)--",
         '<page><body><p><del>strike through</del></p></body></page>'),
        ("normal ~+big __underline__ big+~ normal",
         '<page><body><p>normal <span font-size="120%">big <ins>underline</ins> big</span> normal</p></body></page>'
         ),
        ("/* normal __underline__ normal */",
         '<page><body><p><span class="comment">normal <ins>underline</ins> normal</span></p></body></page>'
         ),
        ('&quot;', '<page><body><p>"</p></body></page>'),
        ('&#34;', '<page><body><p>"</p></body></page>'),
        ('&#x22;', '<page><body><p>"</p></body></page>'),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_inline(self, input, output):
        self.do(input, output)

    data = [
        (' *Item',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>Item</list-item-body></list-item></list></body></page>'
         ),
        (' * Item',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>Item</list-item-body></list-item></list></body></page>'
         ),
        (' 1. Item',
         '<page><body><list item-label-generate="ordered"><list-item><list-item-body>Item</list-item-body></list-item></list></body></page>'
         ),
        (' Key:: Item',
         '<page><body><list><list-item><list-item-label>Key</list-item-label><list-item-body>Item</list-item-body></list-item></list></body></page>'
         ),
        ('  Item',
         '<page><body><list item-label-generate="unordered" list-style-type="no-bullet"><list-item><list-item-body>Item</list-item-body></list-item></list></body></page>'
         ),
        (' *Item\nText',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>Item</list-item-body></list-item></list><p>Text</p></body></page>'
         ),
        (' *Item\n Item',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>Item\nItem</list-item-body></list-item></list></body></page>'
         ),
        (' *Item 1\n *Item 2',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>Item 1</list-item-body></list-item><list-item><list-item-body>Item 2</list-item-body></list-item></list></body></page>'
         ),
        (' *Item 1\n  *Item 1.2\n *Item 2',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>Item 1<list item-label-generate="unordered"><list-item><list-item-body>Item 1.2</list-item-body></list-item></list></list-item-body></list-item><list-item><list-item-body>Item 2</list-item-body></list-item></list></body></page>'
         ),
        (' *List 1\n\n *List 2',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>List 1</list-item-body></list-item></list><list item-label-generate="unordered"><list-item><list-item-body>List 2</list-item-body></list-item></list></body></page>'
         ),
        (' * List 1\n 1. List 2',
         '<page><body><list item-label-generate="unordered"><list-item><list-item-body>List 1</list-item-body></list-item></list><list item-label-generate="ordered"><list-item><list-item-body>List 2</list-item-body></list-item></list></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_list(self, input, output):
        self.do(input, output)

    data = [
        ('<<BR>>', '<page><body /></page>'),
        ('Text<<BR>>Text',
         '<page><body><p>Text<line-break />Text</p></body></page>'),
        ('<<Macro>>',
         '<page><body><part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></body></page>'
         ),
        ('<<Macro>><<Macro>>',
         '<page><body><p><inline-part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /><inline-part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></p></body></page>'
         ),
        ('<<Macro(arg)>>',
         '<page><body><part alt="&lt;&lt;Macro(arg)&gt;&gt;" content-type="x-moin/macro;name=Macro"><arguments>arg</arguments></part></body></page>'
         ),
        # these macro tests copied from test_creole_in, next test is different because leading space creates unordered list in moin2
        (' <<Macro>> ',
         '<page><body><list item-label-generate="unordered" list-style-type="no-bullet"><list-item><list-item-body><part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></list-item-body></list-item></list></body></page>'
         ),
        ('Text <<Macro>>',
         '<page><body><p>Text <inline-part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></p></body></page>'
         ),
        ('Text <<Macro(arg)>>',
         '<page><body><p>Text <inline-part alt="&lt;&lt;Macro(arg)&gt;&gt;" content-type="x-moin/macro;name=Macro"><arguments>arg</arguments></inline-part></p></body></page>'
         ),
        ('Text\n<<Macro>>',
         '<page><body><p>Text</p><part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></body></page>'
         ),
        ('Text\nText <<Macro>>',
         '<page><body><p>Text\nText <inline-part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></p></body></page>'
         ),
        ('Text\n\n<<Macro>>',
         '<page><body><p>Text</p><part alt="&lt;&lt;Macro&gt;&gt;" content-type="x-moin/macro;name=Macro" /></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_macro(self, input, output):
        self.do(input, output)

    data = [
        ('||Cell||',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell>Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||Cell 1||Cell 2||',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell>Cell 1</table-cell><table-cell>Cell 2</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||Row 1||\n||Row 2||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell>Row 1</table-cell></table-row><table-row><table-cell>Row 2</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||Cell 1.1||Cell 1.2||\n||Cell 2.1||Cell 2.2||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell>Cell 1.1</table-cell><table-cell>Cell 1.2</table-cell></table-row><table-row><table-cell>Cell 2.1</table-cell><table-cell>Cell 2.2</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||Header||\n===\n||Body||\n=====\n||Footer||',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell>Header</table-cell></table-row></table-body><table-body><table-row><table-cell>Body</table-cell></table-row></table-body><table-body><table-row><table-cell>Footer</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<<DateTime>>||',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell><inline-part alt="&lt;&lt;DateTime&gt;&gt;" content-type="x-moin/macro;name=DateTime" /></table-cell></table-row></table-body></table></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_table(self, input, output):
        self.do(input, output)

    data = [
        # a class of moin-wiki-table is added to all tables, html_out may create thead and tfoot tags
        ('||||Span||\n\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell number-columns-spanned="2">Span</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<-2>Span||\n\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell number-columns-spanned="2">Span</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<|2>Span||\n\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell number-rows-spanned="2">Span</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<tableclass="table" rowclass="row" class="cell">Cell||\n',
         '<page><body><table class="table moin-wiki-table"><table-body><table-row class="row"><table-cell class="cell">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<tablestyle="table" rowstyle="row" style="cell">Cell||\n',
         '<page><body><table class="moin-wiki-table" style="table;"><table-body><table-row style="row;"><table-cell style="cell;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<tablestyle="background-color: yellow" rowstyle="background-color: red" #0000FF>Cell||\n',
         '<page><body><table class="moin-wiki-table" style="background-color: yellow;"><table-body><table-row style="background-color: red;"><table-cell style="background-color: #0000FF;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<width="20em">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="width: 20em;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<tablebgcolor="red">Cell||\n',
         '<page><body><table class="moin-wiki-table" style="background-color: red;"><table-body><table-row><table-cell>Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<rowbgcolor="red">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row style="background-color: red;"><table-cell>Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<bgcolor="red">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="background-color: red;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<tableid="my-id">Cell||\n',
         '<page><body><table class="moin-wiki-table" id="my-id"><table-body><table-row><table-cell>Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<rowid="my-id">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row id="my-id"><table-cell>Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<id="my-id">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell id="my-id">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<rowspan="2">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell number-rows-spanned="2">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<colspan="2">Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell number-columns-spanned="2">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<caption="My Table">Cell||\n',
         '<page><body><table class="moin-wiki-table"><caption>My Table</caption><table-body><table-row><table-cell>Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ("||'''Cell'''||\n",
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell><strong>Cell</strong></table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<^>Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="vertical-align: top;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<v>Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="vertical-align: bottom;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<(>Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="text-align: left;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<:>Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="text-align: center;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<)>Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="text-align: right;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        ('||<99%>Cell||\n',
         '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="width: 99%;">Cell</table-cell></table-row></table-body></table></body></page>'
         ),
        (
            '||<X>Cell||\n',
            # u'\xa0' below is equal to &nbsp;
            '<page><body><table class="moin-wiki-table"><table-body><table-row><table-cell style="background-color: pink; color: black;">[ Error: "X" is invalid within &lt;X&gt;'
            + '\xa0' +
            ']<line-break />Cell</table-cell></table-row></table-body></table></body></page>'
        ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_table_attributes(self, input, output):
        self.do(input, output)

    data = [
        ('{{{nowiki}}}',
         '<page><body><p><samp>nowiki</samp></p></body></page>'),
        ('`nowiki`', '<page><body><p><code>nowiki</code></p></body></page>'),
        ('{{{{nowiki}}}}',
         '<page><body><p><samp>{nowiki}</samp></p></body></page>'),
        ('text: {{{nowiki}}}, text',
         '<page><body><p>text: <samp>nowiki</samp>, text</p></body></page>'),
        ('{{{\nnowiki\n}}}',
         '<page><body><nowiki>3<nowiki-args></nowiki-args>nowiki</nowiki></body></page>'
         ),
        ('{{{\nnowiki\nno\nwiki\n}}}',
         '<page><body><nowiki>3<nowiki-args></nowiki-args>nowiki\nno\nwiki</nowiki></body></page>'
         ),
        ('{{{nowiki}}} {{{nowiki}}}',
         '<page><body><p><samp>nowiki</samp> <samp>nowiki</samp></p></body></page>'
         ),
        ('{{{}}}', '<page><body><p><samp></samp></p></body></page>'),
        ('``', '<page><body><p><code></code></p></body></page>'),
        # XXX: Is <page> correct?
        ('{{{#!\ntest\n}}}',
         '<page><body><nowiki>3<nowiki-args>#!</nowiki-args>test</nowiki></body></page>'
         ),
        ('{{{#!(style="background-color: red")\nwiki\n}}}',
         '<page><body><nowiki>3<nowiki-args>#!(style="background-color: red")</nowiki-args>wiki</nowiki></body></page>'
         ),
        ('{{{#!text/plain\ntext\n}}}',
         '<page><body><nowiki>3<nowiki-args>#!text/plain</nowiki-args>text</nowiki></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_nowiki(self, input, output):
        self.do(input, output)

    data = [
        ('{{{#!wiki\nwiki\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!wiki</nowiki-args>wiki</nowiki></body></page>"
         ),
        ('{{{{{#!wiki\nwiki\n}}}}}',
         "<page><body><nowiki>5<nowiki-args>#!wiki</nowiki-args>wiki</nowiki></body></page>"
         ),
        ('{{{#!wiki(style="background-color: red")\nwiki\n}}}',
         '<page><body><nowiki>3<nowiki-args>#!wiki(style="background-color: red")</nowiki-args>wiki</nowiki></body></page>'
         ),
        ('{{{#!highlight python\nimport os\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!highlight python</nowiki-args>import os</nowiki></body></page>"
         ),
        ('{{{#!python\nimport os\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!python</nowiki-args>import os</nowiki></body></page>"
         ),
        ('{{{#!csv\na;b;c\nd;e;22\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!csv</nowiki-args>a;b;c\nd;e;22</nowiki></body></page>"
         ),
        ('{{{#!csv ,\na,b,c\nd,e,22\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!csv ,</nowiki-args>a,b,c\nd,e,22</nowiki></body></page>"
         ),
        # TODO: Backward compatibility
        ('{{{#!wiki red/solid\nwiki\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!wiki red/solid</nowiki-args>wiki</nowiki></body></page>"
         ),
        ('{{{#!wiki red/solid\nwiki\n\nwiki\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!wiki red/solid</nowiki-args>wiki\n\nwiki</nowiki></body></page>"
         ),
        ('{{{#!rst\nHeading\n-------\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!rst</nowiki-args>Heading\n-------</nowiki></body></page>"
         ),
        ("{{{#!docbook\n<article xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'>\n<section>\n<title>A docbook document</title>\n</section>\n</article>\n}}}",
         "<page><body><nowiki>3<nowiki-args>#!docbook</nowiki-args>&lt;article xmlns='http://docbook.org/ns/docbook' xmlns:xlink='http://www.w3.org/1999/xlink'&gt;\n&lt;section&gt;\n&lt;title&gt;A docbook document&lt;/title&gt;\n&lt;/section&gt;\n&lt;/article&gt;</nowiki></body></page>"
         ),
        ('{{{#!creole\n|=A|1\n|=B|2\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!creole</nowiki-args>|=A|1\n|=B|2</nowiki></body></page>"
         ),
        ('{{{#!text/x.moin.creole\ntext\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!text/x.moin.creole</nowiki-args>text</nowiki></body></page>"
         ),
        ('{{{#!markdown\n~~~\naaa\nbbb\nccc\n~~~\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!markdown</nowiki-args>~~~\naaa\nbbb\nccc\n~~~</nowiki></body></page>"
         ),
        ('{{{#!mediawiki\n=== Level 3 ===\n}}}',
         "<page><body><nowiki>3<nowiki-args>#!mediawiki</nowiki-args>=== Level 3 ===</nowiki></body></page>"
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_nowiki_parsers(self, input, output):
        self.do(input, output)

    data = [
        ('Text\n * Item\n\nText',
         '<page><body><p>Text</p><list item-label-generate="unordered"><list-item><list-item-body>Item</list-item-body></list-item></list><p>Text</p></body></page>'
         ),
        ('Text\n||Item||\nText',
         '<page><body><p>Text</p><table class="moin-wiki-table"><table-body><table-row><table-cell>Item</table-cell></table-row></table-body></table><p>Text</p></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_composite(self, input, output):
        self.do(input, output)

    data = [
        ('[[MoinMoin:RecentChanges]]',
         '<page><body><p><a xlink:href="wiki://MoinMoin/RecentChanges">RecentChanges</a></p></body></page>'
         ),
        ('[[MoinMoin:RecentChanges|changes]]',
         '<page><body><p><a xlink:href="wiki://MoinMoin/RecentChanges">changes</a></p></body></page>'
         ),
        ('[[MoinMoin:Foo/Bar.Baz]]',
         '<page><body><p><a xlink:href="wiki://MoinMoin/Foo/Bar.Baz">Foo/Bar.Baz</a></p></body></page>'
         ),
        ('[[MoinMoin:Blank In Page Name|blank in page name]]',
         '<page><body><p><a xlink:href="wiki://MoinMoin/Blank%20In%20Page%20Name">blank in page name</a></p></body></page>'
         ),
        ('[[InvalidWikiName:RecentChanges]]',
         '<page><body><p><a xlink:href="wiki.local:InvalidWikiName:RecentChanges">InvalidWikiName:RecentChanges</a></p></body></page>'
         ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_interwiki(self, input, output):
        self.do(input, output)

    data = [
        ('[[mailto:root]]',
         '<page><body><p><a xlink:href="mailto:root">mailto:root</a></p></body></page>'
         ),
        ('[[mailto:[email protected]]]',
         '<page><body><p><a xlink:href="mailto:[email protected]">mailto:[email protected]</a></p></body></page>'
         ),
        ('[[mailto:[email protected]|write me]]',
         '<page><body><p><a xlink:href="mailto:[email protected]">write me</a></p></body></page>'
         ),
        (
            '[[mailto:[email protected]]]',  # . and _ are special characters commonly allowed by email systems
            '<page><body><p><a xlink:href="mailto:[email protected]">mailto:[email protected]</a></p></body></page>'
        ),
    ]

    @pytest.mark.parametrize('input,output', data)
    def test_email(self, input, output):
        self.do(input, output)

    def serialize_strip(self, elem, **options):
        result = serialize(elem, namespaces=self.namespaces, **options)
        return self.output_re.sub('', result)

    def do(self, input, output, args={}, skip=None):
        if skip:
            pytest.skip(skip)
        out = self.conv(input, 'text/x.moin.wiki;charset=utf-8', **args)
        assert self.serialize_strip(out) == output