def test_css_hunks(self): hash_python_png = self.hashing_func( os.path.join(settings.COMPRESS_ROOT, 'img/python.png')) hash_add_png = self.hashing_func( os.path.join(settings.COMPRESS_ROOT, 'img/add.png')) css1 = """\ p { background: url('%(compress_url)simg/python.png?%(hash)s'); } p { background: url(%(compress_url)simg/python.png?%(hash)s); } p { background: url(%(compress_url)simg/python.png?%(hash)s); } p { background: url('%(compress_url)simg/python.png?%(hash)s'); } p { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%(compress_url)simg/python.png?%(hash)s'); } """ % dict(compress_url=self.expected_url_prefix, hash=hash_python_png) css2 = """\ p { background: url('%(compress_url)simg/add.png?%(hash)s'); } p { background: url(%(compress_url)simg/add.png?%(hash)s); } p { background: url(%(compress_url)simg/add.png?%(hash)s); } p { background: url('%(compress_url)simg/add.png?%(hash)s'); } p { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%(compress_url)simg/add.png?%(hash)s'); } """ % dict(compress_url=self.expected_url_prefix, hash=hash_add_png) css = """ <link rel="stylesheet" href="/static/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/static/css/url/2/url2.css" type="text/css"> """ css_node = CssCompressor('css', css) self.assertEqual([css1, css2], list(css_node.hunks()))
def test_filename_in_debug_mode(self): # In debug mode, compressor should look for files using staticfiles # finders only, and not look into the global static directory, where # files can be outdated css_filename = os.path.join(settings.COMPRESS_ROOT, "css", "one.css") # Store the hash of the original file's content with open(css_filename) as f: css_content = f.read() hashed = get_hexdigest(css_content, 12) # Now modify the file in the STATIC_ROOT test_css_content = "p { font-family: 'test' }" with open(css_filename, "a") as css: css.write("\n") css.write(test_css_content) # We should generate a link with the hash of the original content, not # the modified one expected = '<link rel="stylesheet" href="/static/CACHE/css/%s.css" type="text/css" />' % hashed compressor = CssCompressor(self.css) compressor.storage = DefaultStorage() output = compressor.output() self.assertEqual(expected, output) with open(os.path.join(settings.COMPRESS_ROOT, "CACHE", "css", "%s.css" % hashed), "r") as f: result = f.read() self.assertTrue(test_css_content not in result)
def test_css_hunks(self): hash_python_png = self.hashing_func(os.path.join(settings.COMPRESS_ROOT, 'img/python.png')) hash_add_png = self.hashing_func(os.path.join(settings.COMPRESS_ROOT, 'img/add.png')) css1 = """\ p { background: url('%(compress_url)simg/python.png?%(hash)s'); } p { background: url(%(compress_url)simg/python.png?%(hash)s); } p { background: url(%(compress_url)simg/python.png?%(hash)s); } p { background: url('%(compress_url)simg/python.png?%(hash)s'); } p { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%(compress_url)simg/python.png?%(hash)s'); } """ % dict(compress_url=self.expected_url_prefix, hash=hash_python_png) css2 = """\ p { background: url('%(compress_url)simg/add.png?%(hash)s'); } p { background: url(%(compress_url)simg/add.png?%(hash)s); } p { background: url(%(compress_url)simg/add.png?%(hash)s); } p { background: url('%(compress_url)simg/add.png?%(hash)s'); } p { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%(compress_url)simg/add.png?%(hash)s'); } """ % dict(compress_url=self.expected_url_prefix, hash=hash_add_png) css = """ <link rel="stylesheet" href="/static/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/static/css/url/2/url2.css" type="text/css"> """ css_node = CssCompressor(css) self.assertEqual([css1, css2], list(css_node.hunks()))
def test_css_output_with_bom_input(self): out = 'body { background:#990; }\n.compress-test {color: red;}' css = ("""<link rel="stylesheet" href="/static/css/one.css" type="text/css" /> <link rel="stylesheet" href="/static/css/utf-8_with-BOM.css" type="text/css" />""") css_node_with_bom = CssCompressor(css) hunks = '\n'.join([h for h in css_node_with_bom.hunks()]) self.assertEqual(out, hunks)
def setUp(self): self.css = """\ <link rel="stylesheet" href="/media/css/one.css" type="text/css" media="screen"> <style type="text/css" media="print">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" media="all"> <style type="text/css">h1 { border:5px solid green;}</style>""" self.css_node = CssCompressor(self.css)
def render(self, context, compress=settings.COMPRESS, offline=settings.OFFLINE): if compress and offline: key = get_offline_cachekey(self.nodelist) content = cache.get(key) if content: return content content = self.nodelist.render(context) if offline or not compress or not len(content.strip()): return content if self.kind == 'css': compressor = CssCompressor(content) if self.kind == 'js': compressor = JsCompressor(content) cachekey = "%s-%s" % (compressor.cachekey, self.mode) output = self.cache_get(cachekey) if output is None: try: if self.mode == OUTPUT_FILE: output = compressor.output() else: output = compressor.output_inline() self.cache_set(cachekey, output) except: from traceback import format_exc raise Exception(format_exc()) return output
def setUp(self): super(Html5LibParserTests, self).setUp() # special version of the css since the parser sucks self.css = """\ <link href="/media/css/one.css" rel="stylesheet" type="text/css"> <style type="text/css">p { border:5px solid green;}</style> <link href="/media/css/two.css" rel="stylesheet" type="text/css">""" self.css_node = CssCompressor(self.css)
def helper(self, enabled, use_precompiler, use_absolute_filter, expected_output): precompiler = (('text/css', 'compressor.tests.test_base.PassthroughPrecompiler'),) if use_precompiler else () filters = ('compressor.filters.css_default.CssAbsoluteFilter',) if use_absolute_filter else () with self.settings(COMPRESS_ENABLED=enabled, COMPRESS_PRECOMPILERS=precompiler, COMPRESS_CSS_FILTERS=filters): css_node = CssCompressor(self.html_orig) output = list(css_node.hunks())[0] self.assertEqual(output, expected_output)
def setUp(self): self.old_hashing_method = settings.COMPRESS_CSS_HASHING_METHOD settings.COMPRESS_CSS_HASHING_METHOD = self.hashing_method self.css = """ <link rel="stylesheet" href="/static/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/static/css/url/2/url2.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
class PostCompressSignalTestCase(TestCase): def setUp(self): self.css = """\ <link rel="stylesheet" href="/static/css/one.css" type="text/css" /> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css" />""" self.css_node = CssCompressor(self.css) self.js = """\ <script src="/static/js/one.js" type="text/javascript"></script> <script type="text/javascript">obj.value = "value";</script>""" self.js_node = JsCompressor(self.js) def tearDown(self): post_compress.disconnect() def test_js_signal_sent(self): def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) self.js_node.output() args, kwargs = callback.call_args self.assertEqual(JsCompressor, kwargs['sender']) self.assertEqual('js', kwargs['type']) self.assertEqual('file', kwargs['mode']) context = kwargs['context'] assert 'url' in context['compressed'] def test_css_signal_sent(self): def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) self.css_node.output() args, kwargs = callback.call_args self.assertEqual(CssCompressor, kwargs['sender']) self.assertEqual('css', kwargs['type']) self.assertEqual('file', kwargs['mode']) context = kwargs['context'] assert 'url' in context['compressed'] def test_css_signal_multiple_media_attributes(self): css = """\ <link rel="stylesheet" href="/static/css/one.css" media="handheld" type="text/css" /> <style type="text/css" media="print">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css" />""" css_node = CssCompressor(css) def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) css_node.output() self.assertEqual(3, callback.call_count)
class PostCompressSignalTestCase(TestCase): def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_PRECOMPILERS = {} settings.COMPRESS_DEBUG_TOGGLE = 'nocompress' self.css = """\ <link rel="stylesheet" href="/static/css/one.css" type="text/css" /> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css" />""" self.css_node = CssCompressor(self.css) self.js = """\ <script src="/static/js/one.js" type="text/javascript"></script> <script type="text/javascript">obj.value = "value";</script>""" self.js_node = JsCompressor(self.js) def tearDown(self): post_compress.disconnect() def test_js_signal_sent(self): def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) self.js_node.output() args, kwargs = callback.call_args self.assertEquals(JsCompressor, kwargs['sender']) self.assertEquals('js', kwargs['type']) self.assertEquals('file', kwargs['mode']) context = kwargs['context'] assert 'url' in context['compressed'] def test_css_signal_sent(self): def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) self.css_node.output() args, kwargs = callback.call_args self.assertEquals(CssCompressor, kwargs['sender']) self.assertEquals('css', kwargs['type']) self.assertEquals('file', kwargs['mode']) context = kwargs['context'] assert 'url' in context['compressed'] def test_css_signal_multiple_media_attributes(self): css = """\ <link rel="stylesheet" href="/static/css/one.css" media="handheld" type="text/css" /> <style type="text/css" media="print">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css" />""" css_node = CssCompressor(css) def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) css_node.output() self.assertEquals(3, callback.call_count)
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 = ["screen", "print", "all", None, "print"] links = make_soup(css_node.output()).find_all("link") self.assertEqual(media, [l.get("media", None) for l in links])
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_URL = '/media/' settings.COMPRESS_CSS_HASHING_METHOD = 'mtime' self.css = """ <link rel="stylesheet" href="/media/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/media/css/url/2/url2.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
def test_css_output(self): css_node = CssCompressor(self.css) 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 = ['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])
def setUp(self): self.override_settings = self.settings( COMPRESS_CSS_HASHING_METHOD=self.hashing_method) self.override_settings.__enter__() self.css = """ <link rel="stylesheet" href="/static/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/static/css/url/2/url2.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
def setUp(self): self.css = """\ <link rel="stylesheet" href="/static/css/one.css" type="text/css" /> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css" />""" self.css_node = CssCompressor(self.css) self.js = """\ <script src="/static/js/one.js" type="text/javascript"></script> <script type="text/javascript">obj.value = "value";</script>""" self.js_node = JsCompressor(self.js)
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
def test_passthough_when_compress_disabled(self): 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 = make_soup(css_node.output()).find_all(['link', 'style']) self.assertEqual(['/static/css/one.css', '/static/css/two.css', None], [l.get('href', None) for l in output]) self.assertEqual(['screen', 'screen', 'screen'], [l.get('media', None) for l in output])
def test_css_signal_multiple_media_attributes(self): css = """\ <link rel="stylesheet" href="/media/css/one.css" media="handheld" type="text/css" /> <style type="text/css" media="print">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" />""" css_node = CssCompressor(css) def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) css_node.output() self.assertEquals(3, callback.call_count)
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_CSS_FILTERS = [ 'compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.datauri.CssDataUriFilter', ] settings.COMPRESS_URL = '/static/' settings.COMPRESS_CSS_HASHING_METHOD = 'mtime' self.css = """ <link rel="stylesheet" href="/static/css/datauri.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
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
def test_css_signal_multiple_media_attributes(self): css = """\ <link rel="stylesheet" href="/static/css/one.css" media="handheld" type="text/css" /> <style type="text/css" media="print">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css">""" css_node = CssCompressor('css', css) def listener(sender, **kwargs): pass callback = Mock(wraps=listener) post_compress.connect(callback) css_node.output() self.assertEqual(3, callback.call_count)
def setUp(self): settings.COMPRESS_ENABLED = True self.css = """ <link rel="stylesheet" href="/media/css/one.css" type="text/css" charset="utf-8"> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" charset="utf-8"> """ self.css_node = CssCompressor(self.css) self.js = """ <script src="/media/js/one.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8">obj.value = "value";</script> """ self.js_node = JsCompressor(self.js)
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_PRECOMPILERS = {} settings.COMPRESS_DEBUG_TOGGLE = 'nocompress' self.css = """\ <link rel="stylesheet" href="/media/css/one.css" type="text/css" /> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" />""" self.css_node = CssCompressor(self.css) self.js = """\ <script src="/media/js/one.js" type="text/javascript"></script> <script type="text/javascript">obj.value = "value";</script>""" self.js_node = JsCompressor(self.js)
def test_css_single(self): css_node = CssCompressor("""<link rel="stylesheet" href="/media/css/one.css" type="text/css" />""") css_node.opts = {"group_first": "true"} out = [ [ SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u"css", u"one.css"), u"css/one.css", u'<link rel="stylesheet" href="/media/css/one.css" type="text/css" />', ] ] split = css_node.group_contents() split = [[x[0], x[1], x[2], make_elems_str(self.css_node.parser, x[3])] for x in split] self.assertEqual(out, split)
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="/media/css/one.css" type="text/css" media="screen"> <link rel="stylesheet" href="/media/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"/media/css/one.css", u"/media/css/two.css", None], [l.get("href", None) for l in output]) self.assertEqual([u"screen", u"screen", u"screen"], [l.get("media", None) for l in output]) settings.COMPRESS_PRECOMPILERS = original_precompilers
def setUp(self): super(CssAbsolutizingTestCaseWithHash, self).setUp() self.css = """ <link rel="stylesheet" href="/static/css/url/url1.css" type="text/css" charset="utf-8"> <link rel="stylesheet" href="/static/css/url/2/url2.css" type="text/css" charset="utf-8"> """ self.css_node = CssCompressor(self.css)
class CssDataUriTestCase(TestCase): def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_CSS_FILTERS = [ 'compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.datauri.CssDataUriFilter', ] settings.COMPRESS_URL = '/static/' settings.COMPRESS_CSS_HASHING_METHOD = 'mtime' self.css = """ <link rel="stylesheet" href="/static/css/datauri.css" type="text/css"> """ self.css_node = CssCompressor(self.css) def test_data_uris(self): datauri_hash = get_hashed_mtime( os.path.join(settings.COMPRESS_ROOT, 'img/python.png')) out = [ u'''.add { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); } .add-with-hash { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); } .python { background-image: url("/static/img/python.png?%s"); } .datauri { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0 vr4MkhoXe0rZigAAAABJRU5ErkJggg=="); } ''' % datauri_hash ] self.assertEqual(out, list(self.css_node.hunks()))
class Html5LibParserTests(ParserTestCase, CompressorTestCase): parser_cls = 'compressor.parser.Html5LibParser' def setUp(self): super(Html5LibParserTests, self).setUp() # special version of the css since the parser sucks self.css = """\ <link href="/static/css/one.css" rel="stylesheet" type="text/css"> <style type="text/css">p { border:5px solid green;}</style> <link href="/static/css/two.css" rel="stylesheet" type="text/css">""" self.css_node = CssCompressor(self.css) 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 href="/static/css/one.css" rel="stylesheet" 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 href="/static/css/two.css" rel="stylesheet" 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) def test_js_split(self): out = [ (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js', u'one.js'), u'js/one.js', u'<script src="/static/js/one.js" type="text/javascript"></script>'), (SOURCE_HUNK, u'obj.value = "value";', None, u'<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)
class Html5LibParserTests(ParserTestCase, CompressorTestCase): parser_cls = 'compressor.parser.Html5LibParser' def setUp(self): super(Html5LibParserTests, self).setUp() # special version of the css since the parser sucks self.css = """\ <link href="/media/css/one.css" rel="stylesheet" type="text/css"> <style type="text/css">p { border:5px solid green;}</style> <link href="/media/css/two.css" rel="stylesheet" type="text/css">""" self.css_node = CssCompressor(self.css) 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 href="/media/css/one.css" rel="stylesheet" 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 href="/media/css/two.css" rel="stylesheet" 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) def test_js_split(self): out = [ (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js', u'one.js'), u'js/one.js', u'<script src="/media/js/one.js" type="text/javascript"></script>'), (SOURCE_HUNK, u'obj.value = "value";', None, u'<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)
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_URL = '/media/' self.css = """ <link rel="stylesheet" href="/media/css/url/url1.css" type="text/css" charset="utf-8"> <link rel="stylesheet" href="/media/css/url/2/url2.css" type="text/css" charset="utf-8"> """ self.css_node = CssCompressor(self.css)
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_PRECOMPILERS = {} self.css = """\ <link rel="stylesheet" href="/media/css/one.css" type="text/css" /> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/one.less" type="text/less" /> <link rel="stylesheet" href="/media/css/two.less" type="text/less" />""" self.css_node = CssCompressor(self.css) self.css_node.opts = {'group_first': 'true'} self.js = """\ <script src="/media/js/one.js" type="text/javascript"></script> <script type="text/javascript">obj.value = "value";</script> <script src="/media/js/one.coffee" type="text/coffeescript"></script> <script src="/media/js/two.coffee" type="text/coffeescript"></script>""" self.js_node = JsCompressor(self.js)
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="/media/css/one.css" type="text/css" media="screen"> <link rel="stylesheet" href="/media/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'/media/css/one.css', u'/media/css/two.css', None], [l.get('href', None) for l in output]) self.assertEqual([u'screen', u'screen', u'screen'], [l.get('media', None) for l in output]) settings.COMPRESS_PRECOMPILERS = original_precompilers
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_URL = "/media/" settings.COMPRESS_CSS_HASHING_METHOD = "mtime" self.css = """ <link rel="stylesheet" href="/media/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/media/css/url/2/url2.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
def setUp(self): self.override_settings = self.settings(COMPRESS_CSS_HASHING_METHOD=self.hashing_method) self.override_settings.__enter__() self.css = """ <link rel="stylesheet" href="/static/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/static/css/url/2/url2.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
def test_css_single(self): css_node = CssCompressor( """<link rel="stylesheet" href="/media/css/one.css" type="text/css" />""" ) css_node.opts = {'group_first': 'true'} out = [ [ SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'css', u'one.css'), u'css/one.css', u'<link rel="stylesheet" href="/media/css/one.css" type="text/css" />' ], ] split = css_node.group_contents() split = [[ x[0], x[1], x[2], make_elems_str(self.css_node.parser, x[3]) ] for x in split] self.assertEqual(out, split)
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_CSS_FILTERS = [ 'compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.datauri.CssDataUriFilter', ] settings.COMPRESS_URL = '/media/' self.css = """ <link rel="stylesheet" href="/media/css/datauri.css" type="text/css" charset="utf-8"> """ self.css_node = CssCompressor(self.css)
def render_tag(self, context, name, nodelist): request = context['request'] rendered_contents = nodelist.render(context) content = request.media_holder[name].render() if settings.COMPRESS: if name == 'css': compressor = CssCompressor(content) elif name == 'js': compressor = JsCompressor(content) output = self.cache_get(compressor.cachekey) if output is None: try: output = compressor.output() self.cache_set(compressor.cachekey, output) except: from traceback import format_exc raise Exception(format_exc()) else: output = content # no compression return '%s\n%s' % (output, rendered_contents)
def setUp(self): self.old_enabled = settings.COMPRESS_ENABLED self.old_url = settings.COMPRESS_URL self.old_hashing_method = settings.COMPRESS_CSS_HASHING_METHOD settings.COMPRESS_ENABLED = True settings.COMPRESS_URL = '/media/' settings.COMPRESS_CSS_HASHING_METHOD = self.hashing_method self.css = """ <link rel="stylesheet" href="/media/css/url/url1.css" type="text/css"> <link rel="stylesheet" href="/media/css/url/2/url2.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
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
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_CSS_FILTERS = [ 'compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.datauri.CssDataUriFilter', ] settings.COMPRESS_URL = '/media/' settings.COMPRESS_CSS_HASHING_METHOD = 'mtime' self.css = """ <link rel="stylesheet" href="/media/css/datauri.css" type="text/css"> """ self.css_node = CssCompressor(self.css)
def setUp(self): settings.COMPRESS = True self.css = """ <link rel="stylesheet" href="/media/css/one.css" type="text/css" charset="utf-8"> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" charset="utf-8"> """ self.cssNode = CssCompressor(self.css) self.js = """ <script src="/media/js/one.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8">obj.value = "value";</script> """ self.jsNode = JsCompressor(self.js)
class CssDataUriTestCase(TestCase): def setUp(self): self.css = """ <link rel="stylesheet" href="/static/css/datauri.css" type="text/css"> """ self.css_node = CssCompressor(self.css) def test_data_uris(self): datauri_hash = get_hashed_mtime(os.path.join(settings.COMPRESS_ROOT, 'img/python.png')) out = ['''.add { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); } .add-with-hash { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYOkhlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VTUfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKIJ0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJbDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAjbcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAABJRU5ErkJggg=="); } .python { background-image: url("/static/img/python.png?%s"); } .datauri { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0 vr4MkhoXe0rZigAAAABJRU5ErkJggg=="); } ''' % datauri_hash] self.assertEqual(out, list(self.css_node.hunks()))
def setUp(self): settings.COMPRESS_ENABLED = True settings.COMPRESS_PRECOMPILERS = {} self.css = """\ <link rel="stylesheet" href="/media/css/one.css" type="text/css" /> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/one.less" type="text/less" /> <link rel="stylesheet" href="/media/css/two.less" type="text/less" />""" self.css_node = CssCompressor(self.css) self.css_node.opts = {"group_first": "true"} self.js = """\ <script src="/media/js/one.js" type="text/javascript"></script> <script type="text/javascript">obj.value = "value";</script> <script src="/media/js/one.coffee" type="text/coffeescript"></script> <script src="/media/js/two.coffee" type="text/coffeescript"></script>""" self.js_node = JsCompressor(self.js)
class CssMediaTestCase(TestCase): def setUp(self): self.css = """\ <link rel="stylesheet" href="/media/css/one.css" type="text/css" media="screen"> <style type="text/css" media="print">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" media="all"> <style type="text/css">h1 { border:5px solid green;}</style>""" self.css_node = CssCompressor(self.css) def test_css_output(self): links = BeautifulSoup(self.css_node.output()).findAll('link') media = [u'screen', u'print', u'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>' node = CssCompressor(css) media = [u'screen', u'print', u'all', None, u'print'] links = BeautifulSoup(node.output()).findAll('link') self.assertEqual(media, [l.get('media', None) for l in links])
class CompressorTestCase(TestCase): def setUp(self): self.maxDiff = None settings.COMPRESS_ENABLED = True settings.COMPRESS_PRECOMPILERS = {} settings.COMPRESS_DEBUG_TOGGLE = 'nocompress' self.css = """ <link rel="stylesheet" href="/media/css/one.css" type="text/css" charset="utf-8"> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/media/css/two.css" type="text/css" charset="utf-8"> """ self.css_node = CssCompressor(self.css) self.js = """ <script src="/media/js/one.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8">obj.value = "value";</script> """ self.js_node = JsCompressor(self.js) def test_css_split(self): out = [ (SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'css/one.css'), u'css/one.css', u'<link rel="stylesheet" href="/media/css/one.css" type="text/css" charset="utf-8" />'), (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/two.css'), u'css/two.css', u'<link rel="stylesheet" href="/media/css/two.css" type="text/css" charset="utf-8" />'), ] 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) def test_css_hunks(self): out = ['body { background:#990; }', u'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; }' self.assertEqual(out, self.css_node.combined) def test_css_mtimes(self): is_date = re.compile(r'^\d{10}[\.\d]+$') for date in self.css_node.mtimes: self.assertTrue(is_date.match(str(float(date))), "mtimes is returning something that doesn't look like a date: %s" % date) def test_css_return_if_off(self): settings.COMPRESS_ENABLED = False self.assertEqual(self.css, self.css_node.output()) def test_cachekey(self): is_cachekey = re.compile(r'\w{12}') self.assertTrue(is_cachekey.match(self.css_node.cachekey), "cachekey is returning something that doesn't look like r'\w{12}'") def test_css_hash(self): self.assertEqual('c618e6846d04', get_hexdigest(self.css, 12)) def test_css_return_if_on(self): output = css_tag('/media/CACHE/css/e41ba2cc6982.css') self.assertEqual(output, self.css_node.output().strip()) def test_js_split(self): out = [(SOURCE_FILE, os.path.join(settings.COMPRESS_ROOT, u'js/one.js'), u'js/one.js', '<script src="/media/js/one.js" type="text/javascript" charset="utf-8"></script>'), (SOURCE_HUNK, u'obj.value = "value";', None, '<script type="text/javascript" charset="utf-8">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) def test_js_hunks(self): out = ['obj = {};', u'obj.value = "value";'] self.assertEqual(out, list(self.js_node.hunks)) def test_js_concat(self): out = u'obj = {};\nobj.value = "value";' self.assertEqual(out, self.js_node.concat) def test_js_output(self): out = u'obj={};obj.value="value";' self.assertEqual(out, self.js_node.combined) 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 def test_js_return_if_on(self): output = u'<script type="text/javascript" src="/media/CACHE/js/066cd253eada.js" charset="utf-8"></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="/media/custom/js/066cd253eada.js" charset="utf-8"></script>' self.assertEqual(output, JsCompressor(self.js).output()) settings.COMPRESS_OUTPUT_DIR = '' output = u'<script type="text/javascript" src="/media/js/066cd253eada.js" charset="utf-8"></script>' self.assertEqual(output, JsCompressor(self.js).output()) settings.COMPRESS_OUTPUT_DIR = '/custom/nested/' output = u'<script type="text/javascript" src="/media/custom/nested/js/066cd253eada.js" charset="utf-8"></script>' self.assertEqual(output, JsCompressor(self.js).output()) finally: settings.COMPRESS_OUTPUT_DIR = old_output_dir
def test_avoid_reordering_css(self): css = self.css + '<style type="text/css" media="print">p { border:10px solid red;}</style>' node = CssCompressor(css) media = [u'screen', u'print', u'all', None, u'print'] links = BeautifulSoup(node.output()).findAll('link') self.assertEqual(media, [l.get('media', None) for l in links])