############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Tests for the HTMLTALParser code generator. """ import pprint import unittest from zope.tal import htmltalparser, taldefs class TestCaseBase(unittest.TestCase): prologue = "" epilogue = "" initial_program = [('version', taldefs.TAL_VERSION), ('mode', 'html')] final_program = [] def _merge(self, p1, p2): if p1 and p2: op1, args1 = p1[-1] op2, args2 = p2[0] if op1.startswith('rawtext') and op2.startswith('rawtext'): return (p1[:-1] + [rawtext(args1[0] + args2[0])] + p2[1:]) return p1 + p2 def _run_check(self, source, program, macros={}): parser = htmltalparser.HTMLTALParser() parser.parseString(self.prologue + source + self.epilogue) got_program, got_macros = parser.getCode() program = self._merge(self.initial_program, program) program = self._merge(program, self.final_program) self.assertEqual(got_program, program, "Program:\n" + pprint.pformat(got_program) + "\nExpected:\n" + pprint.pformat(program)) self.assertEqual(got_macros, macros, "Macros:\n" + pprint.pformat(got_macros) + "\nExpected:\n" + pprint.pformat(macros)) def _should_error(self, source, exc=taldefs.TALError): def parse(self=self, source=source): parser = htmltalparser.HTMLTALParser() parser.parseString(self.prologue + source + self.epilogue) self.assertRaises(exc, parse) def rawtext(s): """Compile raw text to the appropriate instruction.""" if "\n" in s: return ("rawtextColumn", (s, len(s) - (s.rfind("\n") + 1))) else: return ("rawtextOffset", (s, len(s))) class HTMLTALParserTestCases(TestCaseBase): def test_code_simple_identity(self): self._run_check("""My Title</html>""", [ rawtext('<html a="b" b="c" c="d">' '<title>My Title'), ]) def test_code_implied_list_closings(self): self._run_check("""""", [ rawtext(''), ]) self._run_check("""
""", [ rawtext('
' '
'), ]) def test_code_implied_table_closings(self): self._run_check( """

text
head\t
cell\t""" """""", [ rawtext( '

text

cell \n \t \n
' '\t
head
cell\t' ' \n \t \n
cell
'), ]) self._run_check( """
cell """ """
cell
""", [rawtext('
cell ' '
cell
'), ]) def test_code_bad_nesting(self): def check(self=self): self._run_check("", []) self.assertRaises(htmltalparser.NestingError, check) def test_code_attr_syntax(self): output = [ rawtext(''), ] self._run_check("""""", output) self._run_check("""""", output) self._run_check("""""", output) self._run_check("""""", output) def test_code_attr_values(self): self._run_check( """""", [ rawtext('')]) self._run_check("""""", [ rawtext(''), ]) def test_code_attr_entity_replacement(self): # we expect entities *not* to be replaced by HTLMParser! self._run_check("""""", [ rawtext(''), ]) self._run_check("""""", [ rawtext(''), ]) self._run_check("""""", [ rawtext(''), ]) self._run_check("""""", [ rawtext(''), ]) def test_code_attr_funky_names(self): self._run_check("""""", [ rawtext(''), ]) def test_code_pcdata_entityref(self): self._run_check(""" """, [ rawtext(' '), ]) def test_code_short_endtags(self): self._run_check("""""", [ rawtext(''), ]) class METALGeneratorTestCases(TestCaseBase): def test_null(self): self._run_check("", []) def test_define_macro(self): macro = self.initial_program + [ ('startTag', ('p', [('metal:define-macro', 'M', 'metal')])), rawtext('booh

'), ] program = [ ('setPosition', (1, 0)), ('defineMacro', ('M', macro)), ] macros = {'M': macro} self._run_check('

booh

', program, macros) def test_use_macro(self): self._run_check('

booh

', [ ('setPosition', (1, 0)), ('useMacro', ('M', '$M$', {}, [('startTag', ('p', [('metal:use-macro', 'M', 'metal')])), rawtext('booh

')])), ]) def test_define_slot(self): macro = self.initial_program + [ ('startTag', ('p', [('metal:define-macro', 'M', 'metal')])), rawtext('foo'), ('setPosition', (1, 29)), ('defineSlot', ('S', [('startTag', ('span', [('metal:define-slot', 'S', 'metal')])), rawtext('spam')])), rawtext('bar

'), ] program = [('setPosition', (1, 0)), ('defineMacro', ('M', macro))] macros = {'M': macro} self._run_check('

foo' 'spambar

', program, macros) def test_fill_slot(self): self._run_check( '

foo' 'spambar

', [ ('setPosition', (1, 0)), ('useMacro', ('M', '$M$', {'S': [('startTag', ('span', [('metal:fill-slot', 'S', 'metal')])), rawtext('spam')]}, [('startTag', ('p', [('metal:use-macro', 'M', 'metal')])), rawtext('foo'), ('setPosition', (1, 26)), ('fillSlot', ('S', [ ('startTag', ( 'span', [('metal:fill-slot', 'S', 'metal')])), rawtext('spam')])), rawtext('bar

')])), ]) class TALGeneratorTestCases(TestCaseBase): def test_null(self): self._run_check("", []) def test_define_1(self): self._run_check("

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:define': 'xyzzy string:spam'}), ('setLocal', ('xyzzy', '$string:spam$')), ('startTag', ('p', [('tal:define', 'xyzzy string:spam', 'tal')])), ('endScope', ()), rawtext('

'), ]) def test_define_2(self): self._run_check("

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:define': 'local xyzzy string:spam'}), ('setLocal', ('xyzzy', '$string:spam$')), ('startTag', ('p', [('tal:define', 'local xyzzy string:spam', 'tal')])), ('endScope', ()), rawtext('

'), ]) def test_define_3(self): self._run_check("

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:define': 'global xyzzy string:spam'}), ('setGlobal', ('xyzzy', '$string:spam$')), ('startTag', ('p', [('tal:define', 'global xyzzy string:spam', 'tal')])), ('endScope', ()), rawtext('

'), ]) def test_define_4(self): self._run_check("

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:define': 'x string:spam; y x'}), ('setLocal', ('x', '$string:spam$')), ('setLocal', ('y', '$x$')), ('startTag', ('p', [('tal:define', 'x string:spam; y x', 'tal')])), ('endScope', ()), rawtext('

'), ]) def test_define_5(self): self._run_check("

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:define': 'x string:;;;;; y x'}), ('setLocal', ('x', '$string:;;$')), ('setLocal', ('y', '$x$')), ('startTag', ('p', [('tal:define', 'x string:;;;;; y x', 'tal')])), ('endScope', ()), rawtext('

'), ]) def test_define_6(self): self._run_check( "

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:define': 'x string:spam; global y x; local z y'}), ('setLocal', ('x', '$string:spam$')), ('setGlobal', ('y', '$x$')), ('setLocal', ('z', '$y$')), ('startTag', ('p', [('tal:define', 'x string:spam; global y x; local z y', 'tal')])), ('endScope', ()), rawtext('

'), ]) def test_condition(self): self._run_check( "

foo

", [ rawtext('

'), ('setPosition', (1, 3)), ('beginScope', {'tal:condition': 'python:1'}), ('condition', ('$python:1$', [('startTag', ('span', [('tal:condition', 'python:1', 'tal')])), rawtext('foo')])), ('endScope', ()), rawtext('

'), ]) def test_content_1(self): self._run_check("

bar

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:content': 'string:foo'}), ('startTag', ('p', [('tal:content', 'string:foo', 'tal')])), ('insertText', ('$string:foo$', [rawtext('bar')])), ('endScope', ()), rawtext('

'), ]) def test_content_2(self): self._run_check("

bar

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:content': 'text string:foo'}), ('startTag', ('p', [('tal:content', 'text string:foo', 'tal')])), ('insertText', ('$string:foo$', [rawtext('bar')])), ('endScope', ()), rawtext('

'), ]) def test_content_3(self): self._run_check("

bar

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:content': 'structure string:
'}), ('startTag', ('p', [('tal:content', 'structure string:
', 'tal')])), ('insertStructure', ('$string:
$', {}, [rawtext('bar')])), ('endScope', ()), rawtext('

'), ]) def test_replace_1(self): self._run_check("

bar

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:replace': 'string:foo'}), ('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:replace', 'string:foo', 'tal')]))], [('insertText', ('$string:foo$', [('rawtextOffset', ('bar', 3))]))])), ('endScope', ()), ]) def test_replace_2(self): self._run_check("

bar

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:replace': 'text string:foo'}), ('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:replace', 'text string:foo', 'tal')]))], [('insertText', ('$string:foo$', [('rawtextOffset', ('bar', 3))]))])), ('endScope', ()), ]) def test_replace_3(self): self._run_check( "

bar

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:replace': 'structure string:
'}), ('optTag', ('p', '', None, 0, [('startTag', ( 'p', [( 'tal:replace', 'structure string:
', 'tal')]))], [('insertStructure', ('$string:
$', {}, [ ('rawtextOffset', ('bar', 3))]))])), ('endScope', ()), ]) def test_repeat(self): self._run_check( "

" "dummy

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:repeat': 'x python:(1,2,3)'}), ('loop', ('x', '$python:(1,2,3)$', [('startTag', ('p', [('tal:repeat', 'x python:(1,2,3)', 'tal')])), ('setPosition', (1, 33)), ('beginScope', {'tal:replace': 'x'}), ('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:replace', 'x', 'tal')]))], [('insertText', ('$x$', [('rawtextOffset', ('dummy', 5))]))])), ('endScope', ()), rawtext('

')])), ('endScope', ()), ]) def test_script_1(self): self._run_check('

code

', [ ('setPosition', (1, 0)), ('beginScope', {'tal:script': 'text/server-python'}), ('startTag', ('p', [('tal:script', 'text/server-python', 'tal')])), ('evaluateCode', ('text/server-python', [('rawtextOffset', ('code', 4))])), ('endScope', ()), rawtext('

'), ]) def test_script_2(self): self._run_check( 'code', [ ('setPosition', (1, 0)), ('beginScope', {'script': 'text/server-python'}), ('optTag', ('tal:block', None, 'tal', 0, [('startTag', ('tal:block', [('script', 'text/server-python', 'tal')]))], [('evaluateCode', ('text/server-python', [('rawtextOffset', ('code', 4))]))])), ('endScope', ()) ]) def test_script_3(self): self._run_check('', [ ('setPosition', (1, 0)), ('beginScope', {}), ('optTag', ('script', '', None, 0, [('rawtextOffset', ('', [ ('rawtextOffset', ('', 44)) ]) def test_script_5(self): self._run_check( """""", [ # noqa: E501 line too long ('rawtextOffset', ("""""", # noqa: E501 line too long 64))]) def test_attributes_1(self): self._run_check( "" "link", [ ('setPosition', (1, 0)), ('beginScope', {'tal:attributes': 'href string:http://www.zope.org; x string:y', 'name': 'bar', 'href': 'foo'}), ('startTag', ('a', [('href', 'foo', 'replace', '$string:http://www.zope.org$', 0, None), ('name', 'name="bar"'), ('tal:attributes', 'href string:http://www.zope.org; x string:y', 'tal'), ('x', None, 'insert', '$string:y$', 0, None)])), ('endScope', ()), rawtext('link'), ]) def test_attributes_2(self): self._run_check( "

duh

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:attributes': 'src string:foo.png', 'tal:replace': 'structure string:'}), ('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:replace', 'structure string:', 'tal'), ('tal:attributes', 'src string:foo.png', 'tal')]))], [('insertStructure', ('$string:$', {'src': ('$string:foo.png$', False, None)}, [('rawtextOffset', ('duh', 3))]))])), ('endScope', ())]) def test_on_error_1(self): self._run_check( "

okay

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:content': 'notHere', 'tal:on-error': 'string:error'}), ('onError', ([('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:content', 'notHere', 'tal')])), ('insertText', ('$notHere$', [rawtext('okay')])), rawtext('

')], [('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:content', 'notHere', 'tal')])), ('insertText', ('$string:error$', [])), rawtext('

')])), ('endScope', ()), ]) def test_on_error_2(self): self._run_check( "

okay

", [ ('setPosition', (1, 0)), ('beginScope', {'tal:replace': 'notHere', 'tal:on-error': 'string:error'}), ('onError', ([('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:replace', 'notHere', 'tal')]))], [('insertText', ('$notHere$', [('rawtextOffset', ('okay', 4))]))]))], [('startTag', ('p', [('tal:on-error', 'string:error', 'tal'), ('tal:replace', 'notHere', 'tal')])), ('insertText', ('$string:error$', [])), ('rawtextOffset', ('

', 4))])), ('endScope', ()), ]) def test_dup_attr(self): self._should_error("") self._should_error("", taldefs.METALError) def test_tal_errors(self): self._should_error("

") self._should_error("

") self._should_error("

") self._should_error("

") self._should_error("

") for tag in htmltalparser.EMPTY_HTML_TAGS: self._should_error("<%s tal:content='string:foo'>" % tag) def test_metal_errors(self): exc = taldefs.METALError self._should_error(2 * "

xxx

", exc) self._should_error("" + 2 * "

" + "", exc) self._should_error("

", exc) self._should_error("

", exc) def test_extend_macro_errors(self): exc = taldefs.METALError # extend-macro requires define-macro: self._should_error("

xxx

", exc) # extend-macro prevents use-macro: self._should_error("

xxx

", exc) # use-macro doesn't co-exist with define-macro: self._should_error("

xxx

", exc) # # I18N test cases # def test_i18n_attributes(self): self._run_check("foo", [ ('setPosition', (1, 0)), ('beginScope', {'alt': 'foo', 'i18n:attributes': 'alt'}), ('startTag', ('img', [('alt', 'foo', 'replace', None, 1, None), ('i18n:attributes', 'alt', 'i18n')])), ('endScope', ()), ]) self._run_check("foo", [ ('setPosition', (1, 0)), ('beginScope', {'alt': 'foo', 'i18n:attributes': 'alt foo ; bar'}), ('startTag', ('img', [('alt', 'foo', 'replace', None, 1, 'foo'), ('i18n:attributes', 'alt foo ; bar', 'i18n'), ('bar', None, 'insert', None, 1, None)])), ('endScope', ()), ]) def test_i18n_name_bad_name(self): self._should_error("") self._should_error("") def test_i18n_attributes_repeated_attr(self): self._should_error("") self._should_error("") def test_i18n_translate(self): # input/test19.html self._run_check('''\ Replace this This is a translated string And another translated string ''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('Replace this', 12))])), ('rawtextBeginScope', ('\n', 0, (2, 0), 1, {'i18n:translate': 'msgid'})), ('startTag', ('span', [('i18n:translate', 'msgid', 'i18n')])), ('insertTranslation', ('msgid', [('rawtextColumn', ('This is a\ntranslated string', 17))])), ('rawtextBeginScope', ('\n', 0, (4, 0), 1, {'i18n:translate': ''})), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextColumn', ('And another\ntranslated string', 17))])), ('endScope', ()), ('rawtextColumn', ('\n', 0))]) def test_i18n_translate_with_nested_tal(self): self._run_check('''\ replaceable

content

''', [ # noqa: E501 line too long ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('replaceable ', 12)), ('setPosition', (1, 36)), ('beginScope', {'tal:replace': 'str:here'}), ('optTag', ('p', '', None, 0, [('startTag', ('p', [('tal:replace', 'str:here', 'tal')]))], [('insertText', ('$str:here$', [('rawtextOffset', ('content', 7))]))])), ('endScope', ())])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_name(self): # input/test21.html self._run_check('''\ was born in . ''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextBeginScope', ('\n ', 2, (2, 2), 0, {'i18n:name': 'name', 'tal:replace': 'str:Lomax'})), ('i18nVariable', ('name', [('optTag', ('span', '', None, 1, [('startEndTag', ('span', [('tal:replace', 'str:Lomax', 'tal'), ('i18n:name', 'name', 'i18n')]))], [('insertText', ('$str:Lomax$', []))]))], None, 0)), ('rawtextBeginScope', (' was born in\n ', 2, (3, 2), 1, {'i18n:name': 'country', 'tal:replace': 'str:Antarctica'})), ('i18nVariable', ('country', [('optTag', ('span', '', None, 1, [('startEndTag', ('span', [('tal:replace', 'str:Antarctica', 'tal'), ('i18n:name', 'country', 'i18n')]))], [('insertText', ('$str:Antarctica$', []))]))], None, 0)), ('endScope', ()), ('rawtextColumn', ('.\n', 0))])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_name_with_content(self): self._run_check( '
This is text for ' '.' '
', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('div', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextOffset', ('This is text for ', 17)), ('setPosition', (1, 40)), ('beginScope', {'tal:content': 'bar', 'i18n:name': 'bar_name', 'i18n:translate': ''}), ('i18nVariable', ('bar_name', [('startTag', ('span', [('i18n:translate', '', 'i18n'), ('tal:content', 'bar', 'tal'), ('i18n:name', 'bar_name', 'i18n')])), ('insertI18nText', ('$bar$', [])), ('rawtextOffset', ('
', 7))], None, 0)), ('endScope', ()), ('rawtextOffset', ('.', 1))])), ('endScope', ()), ('rawtextOffset', ('', 6)) ]) def test_i18n_name_implicit_value(self): # input/test22.html self._run_check('''\ Jim was born in the USA. ''', [('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('span', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextBeginScope', ('\n ', 2, (2, 2), 0, {'i18n:name': 'name', 'tal:omit-tag': ''})), ('i18nVariable', ('name', [('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:omit-tag', '', 'tal'), ('i18n:name', 'name', 'i18n')]))], [('rawtextOffset', ('Jim', 10))]))], None, 0)), ('rawtextBeginScope', (' was born in\n ', 2, (3, 2), 1, {'i18n:name': 'country', 'tal:omit-tag': ''})), ('i18nVariable', ('country', [('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:omit-tag', '', 'tal'), ('i18n:name', 'country', 'i18n')]))], [('rawtextOffset', ('the USA', 7))]))], None, 0)), ('endScope', ()), ('rawtextColumn', ('.\n', 0))])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_context_domain(self): self._run_check("", [ ('setPosition', (1, 0)), ('beginI18nContext', {'domain': 'mydomain', 'source': None, 'target': None}), ('beginScope', {'i18n:domain': 'mydomain'}), ('startEndTag', ('span', [('i18n:domain', 'mydomain', 'i18n')])), ('endScope', ()), ('endI18nContext', ()), ]) def test_i18n_context_source(self): self._run_check("", [ ('setPosition', (1, 0)), ('beginI18nContext', {'source': 'en', 'domain': 'default', 'target': None}), ('beginScope', {'i18n:source': 'en'}), ('startEndTag', ('span', [('i18n:source', 'en', 'i18n')])), ('endScope', ()), ('endI18nContext', ()), ]) def test_i18n_context_source_target(self): self._run_check("", [ ('setPosition', (1, 0)), ('beginI18nContext', {'source': 'en', 'target': 'ru', 'domain': 'default'}), ('beginScope', {'i18n:source': 'en', 'i18n:target': 'ru'}), ('startEndTag', ('span', [('i18n:source', 'en', 'i18n'), ('i18n:target', 'ru', 'i18n')])), ('endScope', ()), ('endI18nContext', ()), ]) def test_i18n_context_in_define_slot(self): text = ("
" "
spam
" "
") self._run_check(text, [ ('setPosition', (1, 0)), ('useMacro', ('M', '$M$', {'S': [('startTag', ('div', [('metal:fill-slot', 'S', 'metal')])), rawtext('spam')]}, [('beginI18nContext', {'domain': 'mydomain', 'source': None, 'target': None}), ('beginScope', {'i18n:domain': 'mydomain', 'metal:use-macro': 'M'}), ('startTag', ('div', [('metal:use-macro', 'M', 'metal'), ('i18n:domain', 'mydomain', 'i18n')])), ('setPosition', (1, 48)), ('fillSlot', ('S', [('startTag', ('div', [('metal:fill-slot', 'S', 'metal')])), rawtext('spam')])), ('endScope', ()), rawtext(''), ('endI18nContext', ())])), ]) def test_i18n_data(self): # input/test23.html self._run_check('''\ 2:32 pm ''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': 'timefmt', 'i18n:data': 'here/currentTime'}), ('startTag', ('span', [('i18n:data', 'here/currentTime', 'i18n'), ('i18n:translate', 'timefmt', 'i18n')])), ('insertTranslation', ('timefmt', [('rawtextOffset', ('2:32 pm', 7))], '$here/currentTime$')), ('endScope', ()), ('rawtextColumn', ('
\n', 0)) ]) def test_i18n_data_with_name(self): # input/test29.html self._run_check('''\
At the tone the time will be 2:32 pm... beep!
''', [('setPosition', (1, 0)), ('beginScope', {'i18n:translate': ''}), ('startTag', ('div', [('i18n:translate', '', 'i18n')])), ('insertTranslation', ('', [('rawtextBeginScope', ('At the tone the time will be\n', 0, (2, 0), 0, {'i18n:data': 'here/currentTime', 'i18n:name': 'time', 'i18n:translate': 'timefmt'})), ('i18nVariable', ('time', [('startTag', ('span', [('i18n:data', 'here/currentTime', 'i18n'), ('i18n:translate', 'timefmt', 'i18n'), ('i18n:name', 'time', 'i18n')])), ('insertTranslation', ('timefmt', [('rawtextOffset', ('2:32 pm', 7))], '$here/currentTime$')), ('rawtextOffset', ('
', 7))], None, 0)), ('endScope', ()), ('rawtextOffset', ('... beep!', 9))])), ('endScope', ()), ('rawtextColumn', ('\n', 0)) ]) def test_i18n_name_around_tal_content(self): # input/test28.html self._run_check('''\

Your contact email address is recorded as user@host.com

''', [('setPosition', (1, 0)), ('beginScope', {'i18n:translate': 'verify'}), ('startTag', ('p', [('i18n:translate', 'verify', 'i18n')])), ('insertTranslation', ('verify', [('rawtextBeginScope', ('Your contact email address is recorded as\n ', 4, (2, 4), 0, {'i18n:name': 'email', 'tal:omit-tag': ''})), ('i18nVariable', ('email', [('optTag', ('span', '', None, 0, [('startTag', ('span', [('tal:omit-tag', '', 'tal'), ('i18n:name', 'email', 'i18n')]))], [('rawtextBeginScope', ('\n ', 4, (3, 4), 0, {'href': 'mailto:user@example.com', 'tal:content': 'request/submitter'})), ('startTag', ('a', [('href', 'href="mailto:user@example.com"'), ('tal:content', 'request/submitter', 'tal')])), ('insertText', ('$request/submitter$', [('rawtextOffset', ('user@host.com', 13))])), ('endScope', ()), ('rawtextOffset', ('', 4))]))], None, 0)), ('endScope', ()), ('rawtextColumn', ('\n', 0))])), ('endScope', ()), ('rawtextColumn', ('

\n', 0)) ]) def test_i18n_name_with_tal_content(self): # input/test27.html self._run_check('''\

Your contact email address is recorded as user@host.com

''', [ ('setPosition', (1, 0)), ('beginScope', {'i18n:translate': 'verify'}), ('startTag', ('p', [('i18n:translate', 'verify', 'i18n')])), ('insertTranslation', ('verify', [('rawtextBeginScope', ('Your contact email address is recorded as\n ', 4, (2, 4), 0, {'href': 'mailto:user@example.com', 'i18n:name': 'email', 'tal:content': 'request/submitter'})), ('i18nVariable', ('email', [('startTag', ('a', [('href', 'href="mailto:user@example.com"'), ('tal:content', 'request/submitter', 'tal'), ('i18n:name', 'email', 'i18n')])), ('insertText', ('$request/submitter$', [('rawtextOffset', ('user@host.com', 13))])), ('rawtextOffset', ('', 4))], None, 0)), ('endScope', ()), ('rawtextColumn', ('\n', 0))])), ('endScope', ()), ('rawtextColumn', ('

\n', 0)) ]) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(HTMLTALParserTestCases), unittest.makeSuite(METALGeneratorTestCases), unittest.makeSuite(TALGeneratorTestCases), ))