Files
edx-platform/scripts/xsslint/tests/test_main.py

217 lines
8.2 KiB
Python

# -*- coding: utf-8 -*-
"""
Tests for main.py
"""
import json
import re
from six import StringIO
from unittest import TestCase
import mock
from xsslint.linters import JavaScriptLinter, MakoTemplateLinter, PythonLinter, UnderscoreTemplateLinter
from xsslint.main import _build_ruleset, _lint
from xsslint.reporting import SummaryResults
class TestXSSLinter(TestCase):
"""
Test some top-level linter functions
"""
def setUp(self):
"""
Setup patches on linters for testing.
"""
self.patch_is_valid_directory(MakoTemplateLinter)
self.patch_is_valid_directory(JavaScriptLinter)
self.patch_is_valid_directory(UnderscoreTemplateLinter)
self.patch_is_valid_directory(PythonLinter)
patcher = mock.patch('xsslint.main.is_skip_dir', return_value=False)
patcher.start()
self.addCleanup(patcher.stop)
self.out = StringIO()
self.template_linters = self._build_linters()
self.ruleset = _build_ruleset(self.template_linters)
self.summary_results = SummaryResults(self.ruleset)
def patch_is_valid_directory(self, linter_class):
"""
Creates a mock patch for _is_valid_directory on a Linter to always
return true. This avoids nested patch calls.
Arguments:
linter_class: The linter class to be patched
"""
patcher = mock.patch.object(linter_class, '_is_valid_directory', return_value=True)
patch_start = patcher.start()
self.addCleanup(patcher.stop)
return patch_start
def _build_linters(self):
underscore_linter = UnderscoreTemplateLinter()
python_linter = PythonLinter()
javascript_linter = JavaScriptLinter(underscore_linter=underscore_linter)
mako_linter = MakoTemplateLinter(javascript_linter=javascript_linter, python_linter=python_linter)
return [mako_linter, underscore_linter, javascript_linter, python_linter]
def test_lint_defaults(self):
"""
Tests the top-level linting with default options.
"""
_lint(
'scripts/xsslint/tests/templates',
template_linters=self.template_linters,
options={
'list_files': False,
'verbose': False,
'rule_totals': False,
'summary_format': 'eslint',
'skip_dirs': ()
},
summary_results=self.summary_results,
out=self.out,
)
output = self.out.getvalue()
# Assert violation details are displayed.
assert re.search('test\\.html.*{}'.format(self.ruleset.mako_missing_default.rule_id), output) is not None
assert re.search('test\\.js.*{}'.format(self.ruleset.javascript_concat_html.rule_id), output) is not None
assert re.search('test\\.js.*{}'.format(self.ruleset.underscore_not_escaped.rule_id), output) is not None
lines_with_rule = 0
lines_without_rule = 0 # Output with verbose setting only.
for underscore_match in re.finditer(r'test\.underscore:.*\n', output):
if re.search(self.ruleset.underscore_not_escaped.rule_id, underscore_match.group()) is not None:
lines_with_rule += 1
else:
lines_without_rule += 1
assert lines_with_rule >= 1
assert lines_without_rule == 0
assert re.search('test\\.py.*{}'.format(self.ruleset.python_parse_error.rule_id), output) is None
assert re.search('test\\.py.*{}'.format(self.ruleset.python_wrap_html.rule_id), output) is not None
# Assert no rule totals.
assert re.search('{}:\\s*{} violations'.format(self.ruleset.python_parse_error.rule_id, 0), output) is None
# Assert final total
assert re.search('{} violations total'.format(5), output) is not None
def test_lint_with_verbose(self):
"""
Tests the top-level linting with verbose option.
"""
_lint(
'scripts/xsslint/tests/templates',
template_linters=self.template_linters,
options={
'list_files': False,
'verbose': True,
'rule_totals': False,
'summary_format': 'eslint',
'skip_dirs': ()
},
summary_results=self.summary_results,
out=self.out,
)
output = self.out.getvalue()
lines_with_rule = 0
lines_without_rule = 0 # Output with verbose setting only.
for underscore_match in re.finditer(r'test\.underscore:.*\n', output):
if re.search(self.ruleset.underscore_not_escaped.rule_id, underscore_match.group()) is not None:
lines_with_rule += 1
else:
lines_without_rule += 1
assert lines_with_rule >= 1
assert lines_without_rule >= 1
# Assert no rule totals.
assert re.search('{}:\\s*{} violations'.format(self.ruleset.python_parse_error.rule_id, 0), output) is None
# Assert final total
assert re.search('{} violations total'.format(5), output) is not None
def test_lint_with_rule_totals(self):
"""
Tests the top-level linting with rule totals option.
"""
_lint(
'scripts/xsslint/tests/templates',
template_linters=self.template_linters,
options={
'list_files': False,
'verbose': False,
'rule_totals': True,
'summary_format': 'eslint',
'skip_dirs': ()
},
summary_results=self.summary_results,
out=self.out,
)
output = self.out.getvalue()
assert re.search('test\\.py.*{}'.format(self.ruleset.python_wrap_html.rule_id), output) is not None
# Assert totals output.
assert re.search('{}:\\s*{} violations'.format(self.ruleset.python_parse_error.rule_id, 0), output) is not None
assert re.search('{}:\\s*{} violations'.format(self.ruleset.python_wrap_html.rule_id, 1), output) is not None
assert re.search('{} violations total'.format(5), output) is not None
def test_lint_with_json_output(self):
"""
Tests the top-level linting with JSON summary format.
"""
_lint(
'scripts/xsslint/tests/templates',
template_linters=self.template_linters,
options={
'list_files': False,
'verbose': False,
'rule_totals': True,
'summary_format': 'json',
'skip_dirs': ()
},
summary_results=self.summary_results,
out=self.out,
)
output = self.out.getvalue()
assert re.search('test\\.py.*{}'.format(self.ruleset.python_wrap_html.rule_id), output) is not None
# Find something that looks like pretty-printed JSON
json_match = re.search(r'\n\{.*\n\}', output, re.DOTALL)
assert json_match is not None
data = json.loads(json_match.group())
# Check for rule counts (including zero-instance ones) and total
assert 1 == data['rules']['javascript-concat-html']
assert 0 == data['rules']['python-concat-html']
assert 5 == data['total']
def test_lint_with_list_files(self):
"""
Tests the top-level linting with list files option.
"""
_lint(
'scripts/xsslint/tests/templates',
template_linters=self.template_linters,
options={
'list_files': True,
'verbose': False,
'rule_totals': False,
'summary_format': 'eslint',
'skip_dirs': ()
},
summary_results=self.summary_results,
out=self.out,
)
output = self.out.getvalue()
# Assert file with rule is not output.
assert re.search('test\\.py.*{}'.format(self.ruleset.python_wrap_html.rule_id), output) is None
# Assert file is output.
assert re.search('test\\.py', output) is not None
# Assert no totals.
assert re.search('{}:\\s*{} violations'.format(self.ruleset.python_parse_error.rule_id, 0), output) is None
assert re.search('{} violations total'.format(7), output) is None