mirror of https://github.com/zulip/zulip.git
Improve test coverage for tools.
* Replace generic Exception with TemplateParserException. * Add tests to cover many of the uncovered lines in tools/lib/template_parser.py. * Add an exclusion line to the naïve pattern for checking for missing tuples in format strings, to keep the linter happy.
This commit is contained in:
parent
7070e1ce7c
commit
c9d1a4247f
|
@ -4,6 +4,10 @@ from typing import Callable, Optional
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
class TemplateParserException(Exception):
|
||||||
|
# TODO: Have callers pass in line numbers.
|
||||||
|
pass
|
||||||
|
|
||||||
class TokenizerState(object):
|
class TokenizerState(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -128,7 +132,7 @@ def validate(fn=None, text=None, check_indent=True):
|
||||||
|
|
||||||
def no_start_tag(token):
|
def no_start_tag(token):
|
||||||
# type: (Token) -> None
|
# type: (Token) -> None
|
||||||
raise Exception('''
|
raise TemplateParserException('''
|
||||||
No start tag
|
No start tag
|
||||||
fn: %s
|
fn: %s
|
||||||
end tag:
|
end tag:
|
||||||
|
@ -167,7 +171,7 @@ def validate(fn=None, text=None, check_indent=True):
|
||||||
if end_col != start_col:
|
if end_col != start_col:
|
||||||
problem = 'Bad indentation.'
|
problem = 'Bad indentation.'
|
||||||
if problem:
|
if problem:
|
||||||
raise Exception('''
|
raise TemplateParserException('''
|
||||||
fn: %s
|
fn: %s
|
||||||
%s
|
%s
|
||||||
start:
|
start:
|
||||||
|
@ -238,7 +242,7 @@ def get_handlebars_tag(text, i):
|
||||||
while end < len(text) -1 and text[end] != '}':
|
while end < len(text) -1 and text[end] != '}':
|
||||||
end += 1
|
end += 1
|
||||||
if text[end] != '}' or text[end+1] != '}':
|
if text[end] != '}' or text[end+1] != '}':
|
||||||
raise Exception('Tag missing }}')
|
raise TemplateParserException('Tag missing }}')
|
||||||
s = text[i:end+2]
|
s = text[i:end+2]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@ -248,7 +252,7 @@ def get_django_tag(text, i):
|
||||||
while end < len(text) -1 and text[end] != '%':
|
while end < len(text) -1 and text[end] != '%':
|
||||||
end += 1
|
end += 1
|
||||||
if text[end] != '%' or text[end+1] != '}':
|
if text[end] != '%' or text[end+1] != '}':
|
||||||
raise Exception('Tag missing %}')
|
raise TemplateParserException('Tag missing %}')
|
||||||
s = text[i:end+2]
|
s = text[i:end+2]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@ -261,7 +265,7 @@ def get_html_tag(text, i):
|
||||||
quote_count += 1
|
quote_count += 1
|
||||||
end += 1
|
end += 1
|
||||||
if end == len(text) or text[end] != '>':
|
if end == len(text) or text[end] != '>':
|
||||||
raise Exception('Tag missing >')
|
raise TemplateParserException('Tag missing >')
|
||||||
s = text[i:end+1]
|
s = text[i:end+1]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,9 @@ def build_custom_checkers(by_lang):
|
||||||
# rare; if we find any, they can be added to the exclude list for
|
# rare; if we find any, they can be added to the exclude list for
|
||||||
# this rule.
|
# this rule.
|
||||||
{'pattern': '% [a-zA-Z0-9_.]*\)?$',
|
{'pattern': '% [a-zA-Z0-9_.]*\)?$',
|
||||||
|
'exclude_line': set([
|
||||||
|
('tools/tests/test_template_parser.py', '{% foo'),
|
||||||
|
]),
|
||||||
'description': 'Used % comprehension without a tuple'},
|
'description': 'Used % comprehension without a tuple'},
|
||||||
# To avoid json_error(_variable) and json_error(_(variable))
|
# To avoid json_error(_variable) and json_error(_(variable))
|
||||||
{'pattern': '\Wjson_error\(_\(?\w+\)',
|
{'pattern': '\Wjson_error\(_\(?\w+\)',
|
||||||
|
|
|
@ -6,6 +6,8 @@ import unittest
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from tools.lib.template_parser import (
|
from tools.lib.template_parser import (
|
||||||
|
TemplateParserException,
|
||||||
|
get_tag_info,
|
||||||
html_tag_tree,
|
html_tag_tree,
|
||||||
is_django_block_tag,
|
is_django_block_tag,
|
||||||
tokenize,
|
tokenize,
|
||||||
|
@ -16,6 +18,12 @@ except ImportError:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
class ParserTest(unittest.TestCase):
|
class ParserTest(unittest.TestCase):
|
||||||
|
def _assert_validate_error(self, error, fn=None, text=None, check_indent=True):
|
||||||
|
# See https://github.com/python/typeshed/issues/372
|
||||||
|
# for why we have to ingore types here.
|
||||||
|
with self.assertRaisesRegexp(TemplateParserException, error): # type: ignore
|
||||||
|
validate(fn=fn, text=text, check_indent=check_indent)
|
||||||
|
|
||||||
def test_is_django_block_tag(self):
|
def test_is_django_block_tag(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
self.assertTrue(is_django_block_tag('block'))
|
self.assertTrue(is_django_block_tag('block'))
|
||||||
|
@ -54,6 +62,71 @@ class ParserTest(unittest.TestCase):
|
||||||
'''
|
'''
|
||||||
validate(text=my_html)
|
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_incomplete_handlebars_tag_1(self):
|
||||||
|
# type: () -> None
|
||||||
|
my_html = '''
|
||||||
|
{{# foo
|
||||||
|
'''
|
||||||
|
self._assert_validate_error('Tag missing }}', text=my_html)
|
||||||
|
|
||||||
|
def test_validate_incomplete_handlebars_tag_2(self):
|
||||||
|
# type: () -> None
|
||||||
|
my_html = '''
|
||||||
|
{{# foo }
|
||||||
|
'''
|
||||||
|
self._assert_validate_error('Tag missing }}', text=my_html)
|
||||||
|
|
||||||
|
def test_validate_incomplete_django_tag_1(self):
|
||||||
|
# type: () -> None
|
||||||
|
my_html = '''
|
||||||
|
{% foo
|
||||||
|
'''
|
||||||
|
self._assert_validate_error('Tag missing %}', text=my_html)
|
||||||
|
|
||||||
|
def test_validate_incomplete_django_tag_2(self):
|
||||||
|
# type: () -> None
|
||||||
|
my_html = '''
|
||||||
|
{% foo %
|
||||||
|
'''
|
||||||
|
self._assert_validate_error('Tag missing %}', text=my_html)
|
||||||
|
|
||||||
|
def test_validate_incomplete_html_tag_1(self):
|
||||||
|
# type: () -> None
|
||||||
|
my_html = '''
|
||||||
|
<b
|
||||||
|
'''
|
||||||
|
self._assert_validate_error('Tag missing >', text=my_html)
|
||||||
|
|
||||||
|
def test_validate_incomplete_html_tag_2(self):
|
||||||
|
# type: () -> None
|
||||||
|
my_html = '''
|
||||||
|
<a href="
|
||||||
|
'''
|
||||||
|
self._assert_validate_error('Tag missing >', text=my_html)
|
||||||
|
|
||||||
def test_code_blocks(self):
|
def test_code_blocks(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
|
||||||
|
@ -74,10 +147,7 @@ class ParserTest(unittest.TestCase):
|
||||||
<code>x =
|
<code>x =
|
||||||
5</code>
|
5</code>
|
||||||
'''
|
'''
|
||||||
# See https://github.com/python/typeshed/issues/372
|
self._assert_validate_error('Code tag is split across two lines.', text=my_html)
|
||||||
# for why we have to ingore types here.
|
|
||||||
with self.assertRaisesRegexp(Exception, 'split across two lines'): # type: ignore
|
|
||||||
validate(text=my_html)
|
|
||||||
|
|
||||||
def test_anchor_blocks(self):
|
def test_anchor_blocks(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -145,6 +215,19 @@ class ParserTest(unittest.TestCase):
|
||||||
self.assertEqual(token.kind, 'django_end')
|
self.assertEqual(token.kind, 'django_end')
|
||||||
self.assertEqual(token.tag, 'if')
|
self.assertEqual(token.tag, 'if')
|
||||||
|
|
||||||
|
def test_get_tag_info(self):
|
||||||
|
html = '''
|
||||||
|
<p id="test" class="test1 test2">foo</p>
|
||||||
|
'''
|
||||||
|
|
||||||
|
start_tag, end_tag = tokenize(html)
|
||||||
|
|
||||||
|
start_tag_info = get_tag_info(start_tag)
|
||||||
|
end_tag_info = get_tag_info(end_tag)
|
||||||
|
|
||||||
|
self.assertEqual(start_tag_info.text(), 'p.test1.test2#test')
|
||||||
|
self.assertEqual(end_tag_info.text(), 'p')
|
||||||
|
|
||||||
def test_html_tag_tree(self):
|
def test_html_tag_tree(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
html = '''
|
html = '''
|
||||||
|
|
Loading…
Reference in New Issue