Files
zulip/tools/tests/test_template_parser.py
adnrs96 5b5a0bdb80 Improve check-templates error handling.
In this commit we improve the way errors are handled in our
template parser and thus improving the displayed messages in
case of errors. Eg. Errors in case of unbalanced quotes now
makes more sense displaying line and column information
including line where error might be sourced.
2017-02-22 17:39:12 -08:00

254 lines
7.3 KiB
Python

from __future__ import absolute_import
from __future__ import print_function
from typing import Optional, Any
import sys
import unittest
try:
from tools.lib.template_parser import (
TemplateParserException,
is_django_block_tag,
tokenize,
validate,
)
except ImportError:
print('ERROR!!! You need to run this via tools/test-tools.')
sys.exit(1)
class ParserTest(unittest.TestCase):
def __init__(self, *args, **kwargs):
# type: (*Any, **Any) -> None
# This method should be removed when we migrate to version 3 of Python
import six
if six.PY2:
self.assertRaisesRegex = self.assertRaisesRegexp # type: ignore
super(ParserTest, self).__init__(*args, **kwargs)
def _assert_validate_error(self, error, fn=None, text=None, check_indent=True):
# type: (str, Optional[str], Optional[str], bool) -> None
with self.assertRaisesRegex(TemplateParserException, error): # type: ignore # See https://github.com/python/typeshed/issues/372
validate(fn=fn, text=text, check_indent=check_indent)
def test_is_django_block_tag(self):
# type: () -> None
self.assertTrue(is_django_block_tag('block'))
self.assertFalse(is_django_block_tag('not a django tag'))
def test_validate_vanilla_html(self):
# type: () -> None
'''
Verify that validate() does not raise errors for
well-formed HTML.
'''
my_html = '''
<table>
<tr>
<td>foo</td>
</tr>
</table>'''
validate(text=my_html)
def test_validate_handlebars(self):
# type: () -> None
my_html = '''
{{#with stream}}
<p>{{stream}}</p>
{{/with}}
'''
validate(text=my_html)
def test_validate_comment(self):
# type: () -> None
my_html = '''
<!---
<h1>foo</h1>
-->'''
validate(text=my_html)
def test_validate_django(self):
# type: () -> None
my_html = '''
{% include "some_other.html" %}
{% if foo %}
<p>bar</p>
{% endif %}
'''
validate(text=my_html)
def test_validate_no_start_tag(self):
# type: () -> None
my_html = '''
foo</p>
'''
self._assert_validate_error('No start tag', text=my_html)
def test_validate_mismatched_tag(self):
# type: () -> None
my_html = '''
<b>foo</i>
'''
self._assert_validate_error('Mismatched tag.', text=my_html)
def test_validate_bad_indentation(self):
# type: () -> None
my_html = '''
<p>
foo
</p>
'''
self._assert_validate_error('Bad indentation.', text=my_html, check_indent=True)
def test_validate_state_depth(self):
# type: () -> None
my_html = '''
<b>
'''
self._assert_validate_error('Missing end tag', text=my_html)
def test_validate_incomplete_handlebars_tag_1(self):
# type: () -> None
my_html = '''
{{# foo
'''
self._assert_validate_error('''Tag missing "}}" at Line 2 Col 13:"{{# foo
"''', text=my_html)
def test_validate_incomplete_handlebars_tag_2(self):
# type: () -> None
my_html = '''
{{# foo }
'''
self._assert_validate_error('Tag missing "}}" at Line 2 Col 13:"{{# foo }\n"', text=my_html)
def test_validate_incomplete_django_tag_1(self):
# type: () -> None
my_html = '''
{% foo
'''
self._assert_validate_error('''Tag missing "%}" at Line 2 Col 13:"{% foo
"''', text=my_html)
def test_validate_incomplete_django_tag_2(self):
# type: () -> None
my_html = '''
{% foo %
'''
self._assert_validate_error('Tag missing "%}" at Line 2 Col 13:"{% foo %\n"', text=my_html)
def test_validate_incomplete_html_tag_1(self):
# type: () -> None
my_html = '''
<b
'''
self._assert_validate_error('''Tag missing ">" at Line 2 Col 13:"<b
"''', text=my_html)
def test_validate_incomplete_html_tag_2(self):
# type: () -> None
my_html = '''
<a href="
'''
my_html1 = '''
<a href=""
'''
self._assert_validate_error('''Tag missing ">" at Line 2 Col 13:"<a href=""
"''', text=my_html1)
self._assert_validate_error('''Unbalanced Quotes at Line 2 Col 13:"<a href="
"''', text=my_html)
def test_validate_empty_html_tag(self):
# type: () -> None
my_html = '''
< >
'''
self._assert_validate_error('Tag name missing', text=my_html)
def test_code_blocks(self):
# type: () -> None
# This is fine.
my_html = '''
<code>
x = 5
y = x + 1
</code>'''
validate(text=my_html)
# This is also fine.
my_html = "<code>process_widgets()</code>"
validate(text=my_html)
# This is illegal.
my_html = '''
<code>x =
5</code>
'''
self._assert_validate_error('Code tag is split across two lines.', text=my_html)
def test_anchor_blocks(self):
# type: () -> None
# This is allowed, although strange.
my_html = '''
<a hef="/some/url">
Click here
for more info.
</a>'''
validate(text=my_html)
# This is fine.
my_html = '<a href="/some/url">click here</a>'
validate(text=my_html)
# Even this is fine.
my_html = '''
<a class="twitter-timeline" href="https://twitter.com/ZulipStatus"
data-widget-id="443457763394334720"
data-screen-name="ZulipStatus"
>@ZulipStatus on Twitter</a>.
'''
validate(text=my_html)
def test_tokenize(self):
# type: () -> None
tag = '<meta whatever>bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'html_special')
tag = '<a>bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'html_start')
self.assertEqual(token.tag, 'a')
tag = '<br />bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'html_singleton')
self.assertEqual(token.tag, 'br')
tag = '</a>bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'html_end')
self.assertEqual(token.tag, 'a')
tag = '{{#with foo}}bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'handlebars_start')
self.assertEqual(token.tag, 'with')
tag = '{{/with}}bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'handlebars_end')
self.assertEqual(token.tag, 'with')
tag = '{% if foo %}bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'django_start')
self.assertEqual(token.tag, 'if')
tag = '{% endif %}bla'
token = tokenize(tag)[0]
self.assertEqual(token.kind, 'django_end')
self.assertEqual(token.tag, 'if')