diff options
Diffstat (limited to 'compressor/tests/test_base.py')
| -rw-r--r-- | compressor/tests/test_base.py | 213 |
1 files changed, 128 insertions, 85 deletions
diff --git a/compressor/tests/test_base.py b/compressor/tests/test_base.py index 8678e32..46b1d91 100644 --- a/compressor/tests/test_base.py +++ b/compressor/tests/test_base.py @@ -1,11 +1,16 @@ -from __future__ import with_statement +from __future__ import with_statement, unicode_literals import os import re -from BeautifulSoup import BeautifulSoup +try: + from bs4 import BeautifulSoup +except ImportError: + from BeautifulSoup import BeautifulSoup +from django.utils import six from django.core.cache.backends import locmem -from django.test import TestCase +from django.test import SimpleTestCase +from django.test.utils import override_settings from compressor.base import SOURCE_HUNK, SOURCE_FILE from compressor.conf import settings @@ -14,15 +19,24 @@ from compressor.js import JsCompressor from compressor.exceptions import FilterDoesNotExist +def make_soup(markup): + # we use html.parser instead of lxml because it doesn't work on python 3.3 + if six.PY3: + return BeautifulSoup(markup, 'html.parser') + else: + return BeautifulSoup(markup) + + def css_tag(href, **kwargs): rendered_attrs = ''.join(['%s="%s" ' % (k, v) for k, v in kwargs.items()]) - template = u'<link rel="stylesheet" href="%s" type="text/css" %s/>' + template = '<link rel="stylesheet" href="%s" type="text/css" %s/>' return template % (href, rendered_attrs) class TestPrecompiler(object): """A filter whose output is always the string 'OUTPUT' """ - def __init__(self, content, attrs, filter_type=None, filename=None): + def __init__(self, content, attrs, filter_type=None, filename=None, + charset=None): pass def input(self, **kwargs): @@ -32,11 +46,11 @@ class TestPrecompiler(object): test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__))) -class CompressorTestCase(TestCase): +class CompressorTestCase(SimpleTestCase): def setUp(self): settings.COMPRESS_ENABLED = True - settings.COMPRESS_PRECOMPILERS = {} + settings.COMPRESS_PRECOMPILERS = () settings.COMPRESS_DEBUG_TOGGLE = 'nocompress' self.css = """\ <link rel="stylesheet" href="/static/css/one.css" type="text/css" /> @@ -49,22 +63,52 @@ class CompressorTestCase(TestCase): <script type="text/javascript">obj.value = "value";</script>""" self.js_node = JsCompressor(self.js) + def assertEqualCollapsed(self, a, b): + """ + assertEqual with internal newlines collapsed to single, and + trailing whitespace removed. + """ + collapse = lambda x: re.sub(r'\n+', '\n', x).rstrip() + self.assertEqual(collapse(a), collapse(b)) + + def assertEqualSplits(self, a, b): + """ + assertEqual for splits, particularly ignoring the presence of + a trailing newline on the content. + """ + mangle = lambda split: [(x[0], x[1], x[2], x[3].rstrip()) for x in split] + self.assertEqual(mangle(a), mangle(b)) + def test_css_split(self): out = [ - (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'css', u'one.css'), u'css/one.css', u'<link rel="stylesheet" href="/static/css/one.css" type="text/css" />'), - (SOURCE_HUNK, u'p { border:5px solid green;}', None, u'<style type="text/css">p { border:5px solid green;}</style>'), - (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'css', u'two.css'), u'css/two.css', u'<link rel="stylesheet" href="/static/css/two.css" type="text/css" />'), + ( + SOURCE_FILE, + os.path.join(settings.COMPRESS_ROOT, 'css', 'one.css'), + 'css/one.css', '<link rel="stylesheet" href="/static/css/one.css" type="text/css" />', + ), + ( + SOURCE_HUNK, + 'p { border:5px solid green;}', + None, + '<style type="text/css">p { border:5px solid green;}</style>', + ), + ( + SOURCE_FILE, + os.path.join(settings.COMPRESS_ROOT, 'css', 'two.css'), + 'css/two.css', + '<link rel="stylesheet" href="/static/css/two.css" type="text/css" />', + ), ] split = self.css_node.split_contents() split = [(x[0], x[1], x[2], self.css_node.parser.elem_str(x[3])) for x in split] - self.assertEqual(out, split) + self.assertEqualSplits(split, out) def test_css_hunks(self): - out = ['body { background:#990; }', u'p { border:5px solid green;}', 'body { color:#fff; }'] + out = ['body { background:#990; }', 'p { border:5px solid green;}', 'body { color:#fff; }'] self.assertEqual(out, list(self.css_node.hunks())) def test_css_output(self): - out = u'body { background:#990; }\np { border:5px solid green;}\nbody { color:#fff; }' + out = 'body { background:#990; }\np { border:5px solid green;}\nbody { color:#fff; }' hunks = '\n'.join([h for h in self.css_node.hunks()]) self.assertEqual(out, hunks) @@ -76,7 +120,7 @@ class CompressorTestCase(TestCase): def test_css_return_if_off(self): settings.COMPRESS_ENABLED = False - self.assertEqual(self.css, self.css_node.output()) + self.assertEqualCollapsed(self.css, self.css_node.output()) def test_cachekey(self): is_cachekey = re.compile(r'\w{12}') @@ -89,90 +133,83 @@ class CompressorTestCase(TestCase): def test_js_split(self): out = [ - (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js', u'one.js'), u'js/one.js', '<script src="/static/js/one.js" type="text/javascript"></script>'), - (SOURCE_HUNK, u'obj.value = "value";', None, '<script type="text/javascript">obj.value = "value";</script>'), + ( + SOURCE_FILE, + os.path.join(settings.COMPRESS_ROOT, 'js', 'one.js'), + 'js/one.js', + '<script src="/static/js/one.js" type="text/javascript"></script>', + ), + ( + SOURCE_HUNK, + 'obj.value = "value";', + None, + '<script type="text/javascript">obj.value = "value";</script>', + ), ] split = self.js_node.split_contents() split = [(x[0], x[1], x[2], self.js_node.parser.elem_str(x[3])) for x in split] - self.assertEqual(out, split) + self.assertEqualSplits(split, out) def test_js_hunks(self): - out = ['obj = {};', u'obj.value = "value";'] + out = ['obj = {};', 'obj.value = "value";'] self.assertEqual(out, list(self.js_node.hunks())) def test_js_output(self): - out = u'<script type="text/javascript" src="/static/CACHE/js/066cd253eada.js"></script>' + out = '<script type="text/javascript" src="/static/CACHE/js/066cd253eada.js"></script>' self.assertEqual(out, self.js_node.output()) def test_js_override_url(self): - self.js_node.context.update({'url': u'This is not a url, just a text'}) - out = u'<script type="text/javascript" src="/static/CACHE/js/066cd253eada.js"></script>' + self.js_node.context.update({'url': 'This is not a url, just a text'}) + out = '<script type="text/javascript" src="/static/CACHE/js/066cd253eada.js"></script>' self.assertEqual(out, self.js_node.output()) def test_css_override_url(self): - self.css_node.context.update({'url': u'This is not a url, just a text'}) + self.css_node.context.update({'url': 'This is not a url, just a text'}) output = css_tag('/static/CACHE/css/e41ba2cc6982.css') self.assertEqual(output, self.css_node.output().strip()) + @override_settings(COMPRESS_PRECOMPILERS=(), COMPRESS_ENABLED=False) def test_js_return_if_off(self): - try: - enabled = settings.COMPRESS_ENABLED - precompilers = settings.COMPRESS_PRECOMPILERS - settings.COMPRESS_ENABLED = False - settings.COMPRESS_PRECOMPILERS = {} - self.assertEqual(self.js, self.js_node.output()) - finally: - settings.COMPRESS_ENABLED = enabled - settings.COMPRESS_PRECOMPILERS = precompilers + self.assertEqualCollapsed(self.js, self.js_node.output()) def test_js_return_if_on(self): - output = u'<script type="text/javascript" src="/static/CACHE/js/066cd253eada.js"></script>' + output = '<script type="text/javascript" src="/static/CACHE/js/066cd253eada.js"></script>' self.assertEqual(output, self.js_node.output()) - def test_custom_output_dir(self): - try: - old_output_dir = settings.COMPRESS_OUTPUT_DIR - settings.COMPRESS_OUTPUT_DIR = 'custom' - output = u'<script type="text/javascript" src="/static/custom/js/066cd253eada.js"></script>' - self.assertEqual(output, JsCompressor(self.js).output()) - settings.COMPRESS_OUTPUT_DIR = '' - output = u'<script type="text/javascript" src="/static/js/066cd253eada.js"></script>' - self.assertEqual(output, JsCompressor(self.js).output()) - settings.COMPRESS_OUTPUT_DIR = '/custom/nested/' - output = u'<script type="text/javascript" src="/static/custom/nested/js/066cd253eada.js"></script>' - self.assertEqual(output, JsCompressor(self.js).output()) - finally: - settings.COMPRESS_OUTPUT_DIR = old_output_dir + @override_settings(COMPRESS_OUTPUT_DIR='custom') + def test_custom_output_dir1(self): + output = '<script type="text/javascript" src="/static/custom/js/066cd253eada.js"></script>' + self.assertEqual(output, JsCompressor(self.js).output()) + + @override_settings(COMPRESS_OUTPUT_DIR='') + def test_custom_output_dir2(self): + output = '<script type="text/javascript" src="/static/js/066cd253eada.js"></script>' + self.assertEqual(output, JsCompressor(self.js).output()) + + @override_settings(COMPRESS_OUTPUT_DIR='/custom/nested/') + def test_custom_output_dir3(self): + output = '<script type="text/javascript" src="/static/custom/nested/js/066cd253eada.js"></script>' + self.assertEqual(output, JsCompressor(self.js).output()) + @override_settings(COMPRESS_PRECOMPILERS=( + ('text/foobar', 'compressor.tests.test_base.TestPrecompiler'), + ), COMPRESS_ENABLED=True) def test_precompiler_class_used(self): - try: - original_precompilers = settings.COMPRESS_PRECOMPILERS - settings.COMPRESS_ENABLED = True - settings.COMPRESS_PRECOMPILERS = ( - ('text/foobar', 'compressor.tests.test_base.TestPrecompiler'), - ) - css = '<style type="text/foobar">p { border:10px solid red;}</style>' - css_node = CssCompressor(css) - output = BeautifulSoup(css_node.output('inline')) - self.assertEqual(output.text, 'OUTPUT') - finally: - settings.COMPRESS_PRECOMPILERS = original_precompilers + css = '<style type="text/foobar">p { border:10px solid red;}</style>' + css_node = CssCompressor(css) + output = make_soup(css_node.output('inline')) + self.assertEqual(output.text, 'OUTPUT') + @override_settings(COMPRESS_PRECOMPILERS=( + ('text/foobar', 'compressor.tests.test_base.NonexistentFilter'), + ), COMPRESS_ENABLED=True) def test_nonexistent_precompiler_class_error(self): - try: - original_precompilers = settings.COMPRESS_PRECOMPILERS - settings.COMPRESS_ENABLED = True - settings.COMPRESS_PRECOMPILERS = ( - ('text/foobar', 'compressor.tests.test_base.NonexistentFilter'), - ) - css = '<style type="text/foobar">p { border:10px solid red;}</style>' - css_node = CssCompressor(css) - self.assertRaises(FilterDoesNotExist, css_node.output, 'inline') - finally: - settings.COMPRESS_PRECOMPILERS = original_precompilers - - -class CssMediaTestCase(TestCase): + css = '<style type="text/foobar">p { border:10px solid red;}</style>' + css_node = CssCompressor(css) + self.assertRaises(FilterDoesNotExist, css_node.output, 'inline') + + +class CssMediaTestCase(SimpleTestCase): def setUp(self): self.css = """\ <link rel="stylesheet" href="/static/css/one.css" type="text/css" media="screen"> @@ -182,35 +219,41 @@ class CssMediaTestCase(TestCase): def test_css_output(self): css_node = CssCompressor(self.css) - links = BeautifulSoup(css_node.output()).findAll('link') - media = [u'screen', u'print', u'all', None] + if six.PY3: + links = make_soup(css_node.output()).find_all('link') + else: + links = make_soup(css_node.output()).findAll('link') + media = ['screen', 'print', 'all', None] self.assertEqual(len(links), 4) self.assertEqual(media, [l.get('media', None) for l in links]) def test_avoid_reordering_css(self): css = self.css + '<style type="text/css" media="print">p { border:10px solid red;}</style>' css_node = CssCompressor(css) - media = [u'screen', u'print', u'all', None, u'print'] - links = BeautifulSoup(css_node.output()).findAll('link') + media = ['screen', 'print', 'all', None, 'print'] + if six.PY3: + links = make_soup(css_node.output()).find_all('link') + else: + links = make_soup(css_node.output()).findAll('link') self.assertEqual(media, [l.get('media', None) for l in links]) + @override_settings(COMPRESS_PRECOMPILERS=( + ('text/foobar', 'python %s {infile} {outfile}' % os.path.join(test_dir, 'precompiler.py')), + ), COMPRESS_ENABLED=False) def test_passthough_when_compress_disabled(self): - original_precompilers = settings.COMPRESS_PRECOMPILERS - settings.COMPRESS_ENABLED = False - settings.COMPRESS_PRECOMPILERS = ( - ('text/foobar', 'python %s {infile} {outfile}' % os.path.join(test_dir, 'precompiler.py')), - ) css = """\ <link rel="stylesheet" href="/static/css/one.css" type="text/css" media="screen"> <link rel="stylesheet" href="/static/css/two.css" type="text/css" media="screen"> <style type="text/foobar" media="screen">h1 { border:5px solid green;}</style>""" css_node = CssCompressor(css) - output = BeautifulSoup(css_node.output()).findAll(['link', 'style']) - self.assertEqual([u'/static/css/one.css', u'/static/css/two.css', None], + if six.PY3: + output = make_soup(css_node.output()).find_all(['link', 'style']) + else: + output = make_soup(css_node.output()).findAll(['link', 'style']) + self.assertEqual(['/static/css/one.css', '/static/css/two.css', None], [l.get('href', None) for l in output]) - self.assertEqual([u'screen', u'screen', u'screen'], + self.assertEqual(['screen', 'screen', 'screen'], [l.get('media', None) for l in output]) - settings.COMPRESS_PRECOMPILERS = original_precompilers class VerboseTestCase(CompressorTestCase): |
