Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / cssutils / tests / test_cssutils.py @ 475

History | View | Annotate | Download (17.2 KB)

1
# -*- coding: utf-8 -*-
2
"""Testcases for cssutils.css.CSSCharsetRule"""
3
from __future__ import with_statement
4

    
5
import basetest
6
import codecs
7
import cssutils
8
import os
9
import sys
10
import tempfile
11
import xml.dom
12

    
13
try:
14
    import mock
15
except ImportError:
16
    mock = None
17
    print "install mock library to run all tests"
18

    
19

    
20
class CSSutilsTestCase(basetest.BaseTestCase):
21

    
22
    def setUp(self):
23
        cssutils.ser.prefs.useDefaults()
24

    
25
    def tearDown(self):
26
        cssutils.ser.prefs.useDefaults()
27

    
28
    exp = u'''@import "import/import2.css";
29
.import {
30
    /* ./import.css */
31
    background-image: url(images/example.gif)
32
    }'''
33

    
34
    def test_VERSION(self):
35
        self.assertEqual('1.0', cssutils.VERSION)
36

    
37
    def test_parseString(self):
38
        "cssutils.parseString()"
39
        s = cssutils.parseString(self.exp,
40
                                 media='handheld, screen',
41
                                 title='from string')
42
        self.assertTrue(isinstance(s, cssutils.css.CSSStyleSheet))
43
        self.assertEqual(None, s.href)
44
        self.assertEqual(self.exp.encode(), s.cssText)
45
        self.assertEqual(u'utf-8', s.encoding)
46
        self.assertEqual(u'handheld, screen', s.media.mediaText)
47
        self.assertEqual(u'from string', s.title)
48
        self.assertEqual(self.exp.encode(), s.cssText)
49

    
50
        ir = s.cssRules[0]
51
        self.assertEqual('import/import2.css', ir.href)
52
        irs = ir.styleSheet
53
        self.assertEqual(cssutils.css.CSSStyleSheet, type(irs))
54

    
55
        href = os.path.join(os.path.dirname(__file__),
56
                            '..', '..', '..', 'sheets', 'import.css')
57
        href = cssutils.helper.path2url(href)
58
        s = cssutils.parseString(self.exp,
59
                                 href=href)
60
        self.assertEqual(href, s.href)
61

    
62
        ir = s.cssRules[0]
63
        self.assertEqual('import/import2.css', ir.href)
64
        irs = ir.styleSheet
65
        self.assertTrue(isinstance(irs, cssutils.css.CSSStyleSheet))
66
        self.assertEqual(irs.cssText, '@import "../import3.css";\n@import "import-impossible.css" print;\n.import2 {\n    /* sheets/import2.css */\n    background: url(http://example.com/images/example.gif);\n    background: url(//example.com/images/example.gif);\n    background: url(/images/example.gif);\n    background: url(images2/example.gif);\n    background: url(./images2/example.gif);\n    background: url(../images/example.gif);\n    background: url(./../images/example.gif)\n    }'.encode())
67

    
68
        tests = {
69
                 'a {color: red}': u'a {\n    color: red\n    }',
70
                 'a {color: rgb(1,2,3)}': u'a {\n    color: rgb(1, 2, 3)\n    }'
71
                 }
72
        self.do_equal_p(tests)
73

    
74
    def test_parseFile(self):
75
        "cssutils.parseFile()"
76
        # name if used with open, href used for @import resolving
77
        name = os.path.join(os.path.dirname(__file__),
78
                            '..', '..', '..', 'sheets', 'import.css')
79
        href = cssutils.helper.path2url(name)
80

    
81
        s = cssutils.parseFile(name, href=href, media='screen', title='from file')
82
        self.assertTrue(isinstance(s, cssutils.css.CSSStyleSheet))
83
        if sys.platform.startswith('java'):
84
            # on Jython only file:
85
            self.assertTrue(s.href.startswith('file:'))
86
        else:
87
            # normally file:/// on win and file:/ on unix
88
            self.assertTrue(s.href.startswith('file:/'))
89
        self.assertTrue(s.href.endswith('/sheets/import.css'))
90
        self.assertEqual(u'utf-8', s.encoding)
91
        self.assertEqual(u'screen', s.media.mediaText)
92
        self.assertEqual(u'from file', s.title)
93
        self.assertEqual(self.exp.encode(), s.cssText)
94

    
95
        ir = s.cssRules[0]
96
        self.assertEqual('import/import2.css', ir.href)
97
        irs = ir.styleSheet
98
        self.assertTrue(isinstance(irs, cssutils.css.CSSStyleSheet))
99
        self.assertEqual(irs.cssText, '@import "../import3.css";\n@import "import-impossible.css" print;\n.import2 {\n    /* sheets/import2.css */\n    background: url(http://example.com/images/example.gif);\n    background: url(//example.com/images/example.gif);\n    background: url(/images/example.gif);\n    background: url(images2/example.gif);\n    background: url(./images2/example.gif);\n    background: url(../images/example.gif);\n    background: url(./../images/example.gif)\n    }'.encode())
100

    
101
        # name is used for open and setting of href automatically
102
        # test needs to be relative to this test file!
103
        os.chdir(os.path.dirname(__file__))
104
        name = os.path.join('..', '..', '..', 'sheets', 'import.css')
105

    
106
        s = cssutils.parseFile(name, media='screen', title='from file')
107
        self.assertTrue(isinstance(s, cssutils.css.CSSStyleSheet))
108
        if sys.platform.startswith('java'):
109
            # on Jython only file:
110
            self.assertTrue(s.href.startswith('file:'))
111
        else:
112
            # normally file:/// on win and file:/ on unix
113
            self.assertTrue(s.href.startswith('file:/'))
114
        self.assertTrue(s.href.endswith('/sheets/import.css'))
115
        self.assertEqual(u'utf-8', s.encoding)
116
        self.assertEqual(u'screen', s.media.mediaText)
117
        self.assertEqual(u'from file', s.title)
118
        self.assertEqual(self.exp.encode(), s.cssText)
119

    
120
        ir = s.cssRules[0]
121
        self.assertEqual('import/import2.css', ir.href)
122
        irs = ir.styleSheet
123
        self.assertTrue(isinstance(irs, cssutils.css.CSSStyleSheet))
124
        self.assertEqual(irs.cssText, '@import "../import3.css";\n@import "import-impossible.css" print;\n.import2 {\n    /* sheets/import2.css */\n    background: url(http://example.com/images/example.gif);\n    background: url(//example.com/images/example.gif);\n    background: url(/images/example.gif);\n    background: url(images2/example.gif);\n    background: url(./images2/example.gif);\n    background: url(../images/example.gif);\n    background: url(./../images/example.gif)\n    }'.encode())
125

    
126
        # next test
127
        css = u'a:after { content: "羊蹄€\u2020" }'
128

    
129
        fd, name = tempfile.mkstemp('_cssutilstest.css')
130
        t = os.fdopen(fd, 'wb')
131
        t.write(css.encode('utf-8'))
132
        t.close()
133

    
134
        self.assertRaises(UnicodeDecodeError, cssutils.parseFile, name, 'ascii')
135

    
136
        # ???
137
        s = cssutils.parseFile(name, encoding='iso-8859-1')
138
        self.assertEqual(cssutils.css.CSSStyleSheet, type(s))
139
        self.assertEqual(s.cssRules[1].selectorText, 'a:after')
140

    
141
        s = cssutils.parseFile(name, encoding='utf-8')
142
        self.assertEqual(cssutils.css.CSSStyleSheet, type(s))
143
        self.assertEqual(s.cssRules[1].selectorText, 'a:after')
144

    
145
        css = u'@charset "iso-8859-1"; a:after { content: "ä" }'
146
        t = codecs.open(name, 'w', 'iso-8859-1')
147
        t.write(css)
148
        t.close()
149

    
150
        self.assertRaises(
151
            UnicodeDecodeError, cssutils.parseFile, name, 'ascii')
152

    
153
        s = cssutils.parseFile(name, encoding='iso-8859-1')
154
        self.assertEqual(cssutils.css.CSSStyleSheet, type(s))
155
        self.assertEqual(s.cssRules[1].selectorText, 'a:after')
156

    
157
        self.assertRaises(
158
            UnicodeDecodeError, cssutils.parseFile, name, 'utf-8')
159

    
160
        # clean up
161
        try:
162
            os.remove(name)
163
        except OSError, e:
164
            pass
165

    
166
    def test_parseUrl(self):
167
        "cssutils.parseUrl()"
168
        href = os.path.join(os.path.dirname(__file__),
169
                            '..', '..', '..', 'sheets', 'import.css')
170
        #href = u'file:' + urllib.pathname2url(href)
171
        href = cssutils.helper.path2url(href)
172
        #href = 'http://seewhatever.de/sheets/import.css'
173
        s = cssutils.parseUrl(href,
174
                              media='tv, print',
175
                              title='from url')
176
        self.assertTrue(isinstance(s, cssutils.css.CSSStyleSheet))
177
        self.assertEqual(href, s.href)
178
        self.assertEqual(self.exp.encode(), s.cssText)
179
        self.assertEqual(u'utf-8', s.encoding)
180
        self.assertEqual(u'tv, print', s.media.mediaText)
181
        self.assertEqual('from url', s.title)
182

    
183
        sr = s.cssRules[1]
184
        img = sr.style.getProperty('background-image').propertyValue[0].value
185
        self.assertEqual(img, 'images/example.gif')
186

    
187
        ir = s.cssRules[0]
188
        self.assertEqual(u'import/import2.css', ir.href)
189
        irs = ir.styleSheet
190
        self.assertEqual(irs.cssText, '@import "../import3.css";\n@import "import-impossible.css" print;\n.import2 {\n    /* sheets/import2.css */\n    background: url(http://example.com/images/example.gif);\n    background: url(//example.com/images/example.gif);\n    background: url(/images/example.gif);\n    background: url(images2/example.gif);\n    background: url(./images2/example.gif);\n    background: url(../images/example.gif);\n    background: url(./../images/example.gif)\n    }'.encode())
191

    
192
        ir2 = irs.cssRules[0]
193
        self.assertEqual(u'../import3.css', ir2.href)
194
        irs2 = ir2.styleSheet
195
        self.assertEqual(irs2.cssText, '/* import3 */\n.import3 {\n    /* from ./import/../import3.css */\n    background: url(images/example3.gif);\n    background: url(./images/example3.gif);\n    background: url(import/images2/example2.gif);\n    background: url(./import/images2/example2.gif);\n    background: url(import/images2/../../images/example3.gif)\n    }'.encode())
196

    
197
    def test_setCSSSerializer(self):
198
        "cssutils.setSerializer() and cssutils.ser"
199
        s = cssutils.parseString('a { left: 0 }')
200
        exp4 = '''a {
201
    left: 0
202
    }'''
203
        exp1 = '''a {
204
 left: 0
205
 }'''
206
        self.assertEqual(exp4.encode(), s.cssText)
207
        newser = cssutils.CSSSerializer(cssutils.serialize.Preferences(indent=' '))
208
        cssutils.setSerializer(newser)
209
        self.assertEqual(exp1.encode(), s.cssText)
210
        newser = cssutils.CSSSerializer(cssutils.serialize.Preferences(indent='    '))
211
        cssutils.ser = newser
212
        self.assertEqual(exp4.encode(), s.cssText)
213

    
214
    def test_parseStyle(self):
215
        "cssutils.parseStyle()"
216
        s = cssutils.parseStyle('x:0; y:red')
217
        self.assertEqual(type(s), cssutils.css.CSSStyleDeclaration)
218
        self.assertEqual(s.cssText,  u'x: 0;\ny: red')
219

    
220
        s = cssutils.parseStyle('@import "x";')
221
        self.assertEqual(type(s), cssutils.css.CSSStyleDeclaration)
222
        self.assertEqual(s.cssText, u'')
223

    
224
        tests = [
225
            (u'content: "ä"', 'iso-8859-1'),
226
            (u'content: "€"', 'utf-8')
227
        ]
228
        for v, e in tests:
229
            s = cssutils.parseStyle(v.encode(e), encoding=e)
230
            self.assertEqual(s.cssText, v)
231

    
232
        self.assertRaises(UnicodeDecodeError, cssutils.parseStyle,
233
                          u'content: "ä"'.encode('utf-8'), 'ascii')
234

    
235

    
236
    def test_getUrls(self):
237
        "cssutils.getUrls()"
238
        cssutils.ser.prefs.keepAllProperties = True
239

    
240
        css='''
241
        @import "im1";
242
        @import url(im2);
243
        @import url( im3 );
244
        @import url( "im4" );
245
        @import url( 'im5' );
246
        a {
247
            background-image: url(a) !important;
248
            background-\image: url(b);
249
            background: url(c) no-repeat !important;
250
            /* issue #46 */
251
            src: local("xx"),
252
                 url("f.woff") format("woff"),
253
                 url("f.otf") format("opentype"),
254
                 url("f.svg#f") format("svg");
255
            }'''
256
        urls = set(cssutils.getUrls(cssutils.parseString(css)))
257
        self.assertEqual(urls, set(["im1", "im2", "im3", "im4", "im5",
258
                                    "a", "b", "c",
259
                                    u'f.woff', u'f.svg#f', u'f.otf']))
260
        cssutils.ser.prefs.keepAllProperties = False
261

    
262
    def test_replaceUrls(self):
263
        "cssutils.replaceUrls()"
264
        cssutils.ser.prefs.keepAllProperties = True
265

    
266
        css='''
267
        @import "im1";
268
        @import url(im2);
269
        a {
270
            background-image: url(c) !important;
271
            background-\image: url(b);
272
            background: url(a) no-repeat !important;
273
            }'''
274
        s = cssutils.parseString(css)
275
        cssutils.replaceUrls(s, lambda old: "NEW" + old)
276
        self.assertEqual(u'@import "NEWim1";', s.cssRules[0].cssText)
277
        self.assertEqual(u'NEWim2', s.cssRules[1].href)
278
        self.assertEqual(u'''background-image: url(NEWc) !important;
279
background-\\image: url(NEWb);
280
background: url(NEWa) no-repeat !important''', s.cssRules[2].style.cssText)
281

    
282
        cssutils.ser.prefs.keepAllProperties = False
283

    
284
        # CSSStyleDeclaration
285
        style = cssutils.parseStyle(u'''color: red;
286
                                        background-image:
287
                                            url(1.png),
288
                                            url('2.png')''')
289
        cssutils.replaceUrls(style, lambda url: 'prefix/'+url)
290
        self.assertEqual(style.cssText, u'''color: red;
291
background-image: url(prefix/1.png), url(prefix/2.png)''')
292

    
293

    
294
    def test_resolveImports(self):
295
        "cssutils.resolveImports(sheet)"
296
        if mock:
297
            self._tempSer()
298
            cssutils.ser.prefs.useMinified()
299

    
300
            a = u'@charset "iso-8859-1";@import"b.css";\xe4{color:green}'.encode('iso-8859-1')
301
            b = u'@charset "ascii";\\E4 {color:red}'.encode('ascii')
302

    
303
            # normal
304
            m = mock.Mock()
305
            with mock.patch('cssutils.util._defaultFetcher', m):
306
                m.return_value = (None, b)
307
                s = cssutils.parseString(a)
308

    
309
                # py3 TODO
310
                self.assertEqual(a, s.cssText)
311
                self.assertEqual(b, s.cssRules[1].styleSheet.cssText)
312

    
313
                c = cssutils.resolveImports(s)
314

    
315
                # py3 TODO
316
                self.assertEqual(u'\xc3\xa4{color:red}\xc3\xa4{color:green}'.encode('iso-8859-1'),
317
                                 c.cssText)
318

    
319
                c.encoding = 'ascii'
320
                self.assertEqual(ur'@charset "ascii";\E4 {color:red}\E4 {color:green}'.encode(),
321
                                 c.cssText)
322

    
323
            # b cannot be found
324
            m = mock.Mock()
325
            with mock.patch('cssutils.util._defaultFetcher', m):
326
                m.return_value = (None, None)
327
                s = cssutils.parseString(a)
328

    
329
                # py3 TODO
330
                self.assertEqual(a, s.cssText)
331
                self.assertEqual(cssutils.css.CSSStyleSheet,
332
                                 type(s.cssRules[1].styleSheet))
333
                c = cssutils.resolveImports(s)
334
                # py3 TODO
335
                self.assertEqual(u'@import"b.css";\xc3\xa4{color:green}'.encode('iso-8859-1'),
336
                                 c.cssText)
337

    
338
            # @import with media
339
            a = u'@import"b.css";@import"b.css" print, tv ;@import"b.css" all;'
340
            b = u'a {color: red}'
341
            m = mock.Mock()
342
            with mock.patch('cssutils.util._defaultFetcher', m):
343
                m.return_value = (None, b)
344
                s = cssutils.parseString(a)
345

    
346
                c = cssutils.resolveImports(s)
347

    
348
                self.assertEqual('a{color:red}@media print,tv{a{color:red}}a{color:red}'.encode(),
349
                                 c.cssText)
350

    
351
            # cannot resolve with media => keep original
352
            a = u'@import"b.css"print;'
353
            b = u'@namespace "http://example.com";'
354
            m = mock.Mock()
355
            with mock.patch('cssutils.util._defaultFetcher', m):
356
                m.return_value = (None, b)
357
                s = cssutils.parseString(a)
358
                c = cssutils.resolveImports(s)
359
                self.assertEqual(a.encode(), c.cssText)
360

    
361
            # urls are adjusted too, layout:
362
            # a.css
363
            # c.css
364
            # img/img.gif
365
            # b/
366
            #     b.css
367
            #     subimg/subimg.gif
368
            a = u'''
369
                 @import"b/b.css";
370
                 a {
371
                     x: url(/img/abs.gif);
372
                     y: url(img/img.gif);
373
                     z: url(b/subimg/subimg.gif);
374
                     }'''
375
            def fetcher(url):
376
                c = {
377
                     'b.css': u'''
378
                         @import"../c.css";
379
                         b {
380
                             x: url(/img/abs.gif);
381
                             y: url(../img/img.gif);
382
                             z: url(subimg/subimg.gif);
383
                             }''',
384
                     'c.css': u'''
385
                         c {
386
                             x: url(/img/abs.gif);
387
                             y: url(./img/img.gif);
388
                             z: url(./b/subimg/subimg.gif);
389
                             }'''
390
                     }
391
                return 'utf-8', c[os.path.split(url)[1]]
392

    
393
            @mock.patch.object(cssutils.util, '_defaultFetcher',
394
                               new=fetcher)
395
            def do():
396
                s = cssutils.parseString(a)
397
                r = cssutils.resolveImports(s)
398
                return s, r
399

    
400
            s, r = do()
401

    
402
            cssutils.ser.prefs.useDefaults()
403
            cssutils.ser.prefs.keepComments = False
404
            self.assertEqual(u'''c {
405
    x: url(/img/abs.gif);
406
    y: url(img/img.gif);
407
    z: url(b/subimg/subimg.gif)
408
    }
409
b {
410
    x: url(/img/abs.gif);
411
    y: url(img/img.gif);
412
    z: url(b/subimg/subimg.gif)
413
    }
414
a {
415
    x: url(/img/abs.gif);
416
    y: url(img/img.gif);
417
    z: url(b/subimg/subimg.gif)
418
    }'''.encode(), r.cssText)
419

    
420
            cssutils.ser.prefs.useDefaults()
421
        else:
422
            self.assertEqual(False, u'Mock needed for this test')
423

    
424
if __name__ == '__main__':
425
    import unittest
426
    unittest.main()