summaryrefslogtreecommitdiff
path: root/compressor/tests/test_parsers.py
blob: e5266d9202b3cb36256d9e2a026064f1b3a9f9fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import os
import unittest

try:
    import lxml
except ImportError:
    lxml = None

try:
    import html5lib
except ImportError:
    html5lib = None

from django.test.utils import override_settings

from compressor.base import SOURCE_HUNK, SOURCE_FILE
from compressor.conf import settings
from compressor.tests.test_base import CompressorTestCase


class ParserTestCase:
    def setUp(self):
        self.override_settings = self.settings(COMPRESS_PARSER=self.parser_cls)
        self.override_settings.__enter__()
        super().setUp()

    def tearDown(self):
        self.override_settings.__exit__(None, None, None)


@unittest.skipIf(lxml is None, "lxml not found")
class LxmlParserTests(ParserTestCase, CompressorTestCase):
    parser_cls = "compressor.parser.LxmlParser"


@unittest.skipIf(html5lib is None, "html5lib not found")
class Html5LibParserTests(ParserTestCase, CompressorTestCase):
    parser_cls = "compressor.parser.Html5LibParser"
    # Special test variants required since xml.etree holds attributes
    # as a plain dictionary, e.g. key order is unpredictable.

    def test_css_split(self):
        split = self.css_node.split_contents()
        out0 = (
            SOURCE_FILE,
            os.path.join(settings.COMPRESS_ROOT, "css", "one.css"),
            "css/one.css",
            "{http://www.w3.org/1999/xhtml}link",
            {"rel": "stylesheet", "href": "/static/css/one.css", "type": "text/css"},
        )
        self.assertEqual(out0, split[0][:3] + (split[0][3].tag, split[0][3].attrib))
        out1 = (
            SOURCE_HUNK,
            "p { border:5px solid green;}",
            None,
            '<style type="text/css">p { border:5px solid green;}</style>',
        )
        self.assertEqual(
            out1, split[1][:3] + (self.css_node.parser.elem_str(split[1][3]),)
        )
        out2 = (
            SOURCE_FILE,
            os.path.join(settings.COMPRESS_ROOT, "css", "two.css"),
            "css/two.css",
            "{http://www.w3.org/1999/xhtml}link",
            {"rel": "stylesheet", "href": "/static/css/two.css", "type": "text/css"},
        )
        self.assertEqual(out2, split[2][:3] + (split[2][3].tag, split[2][3].attrib))

    def test_js_split(self):
        split = self.js_node.split_contents()
        out0 = (
            SOURCE_FILE,
            os.path.join(settings.COMPRESS_ROOT, "js", "one.js"),
            "js/one.js",
            "{http://www.w3.org/1999/xhtml}script",
            {"src": "/static/js/one.js", "type": "text/javascript"},
            None,
        )
        self.assertEqual(
            out0, split[0][:3] + (split[0][3].tag, split[0][3].attrib, split[0][3].text)
        )
        out1 = (
            SOURCE_HUNK,
            'obj.value = "value";',
            None,
            "{http://www.w3.org/1999/xhtml}script",
            {"type": "text/javascript"},
            'obj.value = "value";',
        )
        self.assertEqual(
            out1, split[1][:3] + (split[1][3].tag, split[1][3].attrib, split[1][3].text)
        )

    @override_settings(COMPRESS_ENABLED=False)
    def test_css_return_if_off(self):
        # Yes, they are semantically equal but attributes might be
        # scrambled in unpredictable order. A more elaborate check
        # would require parsing both arguments with a different parser
        # and then evaluating the result, which no longer is
        # a meaningful unit test.
        self.assertEqual(len(self.css), len(self.css_node.output()))

    @override_settings(COMPRESS_PRECOMPILERS=(), COMPRESS_ENABLED=False)
    def test_js_return_if_off(self):
        # As above.
        self.assertEqual(len(self.js), len(self.js_node.output()))


class BeautifulSoupParserTests(ParserTestCase, CompressorTestCase):
    parser_cls = "compressor.parser.BeautifulSoupParser"
    # just like in the Html5LibParserTests, provide special tests because
    # in bs4 attributes are held in dictionaries

    def test_css_split(self):
        split = self.css_node.split_contents()
        out0 = (
            SOURCE_FILE,
            os.path.join(settings.COMPRESS_ROOT, "css", "one.css"),
            "css/one.css",
            None,
            None,
        )
        self.assertEqual(out0, split[0][:3] + (split[0][3].tag, split[0][3].attrib))
        out1 = (
            SOURCE_HUNK,
            "p { border:5px solid green;}",
            None,
            '<style type="text/css">p { border:5px solid green;}</style>',
        )
        self.assertEqual(
            out1, split[1][:3] + (self.css_node.parser.elem_str(split[1][3]),)
        )
        out2 = (
            SOURCE_FILE,
            os.path.join(settings.COMPRESS_ROOT, "css", "two.css"),
            "css/two.css",
            None,
            None,
        )
        self.assertEqual(out2, split[2][:3] + (split[2][3].tag, split[2][3].attrib))

    @override_settings(COMPRESS_ENABLED=False)
    def test_css_return_if_off(self):
        self.assertEqual(len(self.css), len(self.css_node.output()))


class HtmlParserTests(ParserTestCase, CompressorTestCase):
    parser_cls = "compressor.parser.HtmlParser"