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_selector.py @ 475

History | View | Annotate | Download (16.1 KB)

1
"""Testcases for cssutils.css.selector.Selector.
2

3
what should happen here?
4
    - star 7 hack::
5
        x*
6
        does not validate but works in IE>5 and FF, does it???
7

8
"""
9
import xml.dom
10
import basetest
11
import cssutils
12

    
13
class SelectorTestCase(basetest.BaseTestCase):
14

    
15
    def setUp(self):
16
        self.r = cssutils.css.Selector('*')
17

    
18
    def test_init(self):
19
        "Selector.__init__()"
20
        s = cssutils.css.Selector('*')
21
        self.assertEqual((None, '*'), s.element)
22
        self.assertEqual({}, s._namespaces.namespaces)
23
        self.assertEqual(None, s.parent)
24
        self.assertEqual('*', s.selectorText)
25
        self.assertEqual((0,0,0,0), s.specificity)
26
        self.assertEqual(True, s.wellformed)
27

    
28
        s = cssutils.css.Selector(('p|b', {'p': 'URI'}) )
29
        self.assertEqual(('URI', 'b'), s.element)
30
        self.assertEqual({'p': 'URI'}, s._namespaces.namespaces)
31
        self.assertEqual(None, s.parent)
32
        self.assertEqual('p|b', s.selectorText)
33
        self.assertEqual((0,0,0,1), s.specificity)
34
        self.assertEqual(True, s.wellformed)
35

    
36
        self.assertRaisesEx(xml.dom.NamespaceErr, cssutils.css.Selector, 'p|b')
37

    
38
    def test_element(self):
39
        "Selector.element (TODO: RESOLVE)"
40
        tests = {
41
            '*': (None, '*'),
42
            'x': (None, 'x'),
43
            '\\x': (None, '\\x'),
44
            '|x': (u'', 'x'),
45
            '*|x': (cssutils._ANYNS, 'x'),
46
            'ex|x': (u'example', 'x'),
47
            'a x': (None, 'x'),
48
            'a+x': (None, 'x'),
49
            'a>x': (None, 'x'),
50
            'a~x': (None, 'x'),
51
            'a+b~c x': (None, 'x'),
52
            'x[href]': (None, 'x'),
53
            'x[href="123"]': (None, 'x'),
54
            'x:hover': (None, 'x'),
55
            'x:first-letter': (None, 'x'), # TODO: Really?
56
            'x::first-line': (None, 'x'), # TODO: Really?
57
            'x:not(href)': (None, 'x'), # TODO: Really?
58

    
59
            '#id': None,
60
            '.c': None,
61
            'x#id': (None, 'x'),
62
            'x.c': (None, 'x')
63
        }
64
        for test, ele in tests.items():
65
            s = cssutils.css.Selector((test,{'ex': 'example'}))
66
            self.assertEqual(ele, s.element)
67

    
68
    def test_namespaces(self):
69
        "Selector.namespaces"
70
        namespaces = [
71
            {'p': 'other'}, # no default
72
            {'': 'default', 'p': 'other'}, # with default
73
            {'': 'default', 'p': 'default' } # same default
74
            ]
75
        tests = {
76
            # selector: with default, no default, same default
77
            '*': ('*', '*', '*'),
78
            'x': ('x', 'x', 'x'),
79
            '|*': ('|*', '|*', '|*'),
80
            '|x': ('|x', '|x', '|x'),
81
            '*|*': ('*|*', '*|*', '*|*'),
82
            '*|x': ('*|x', '*|x', '*|x'),
83
            'p|*': ('p|*', 'p|*', '*'),
84
            'p|x': ('p|x', 'p|x', 'x'),
85
            'x[a][|a][*|a][p|a]': ('x[a][a][*|a][p|a]',
86
                                   'x[a][a][*|a][p|a]',
87
                                   'x[a][a][*|a][a]')
88
        }
89
        for sel, exp in tests.items():
90
            for i, result in enumerate(exp):
91
                s = cssutils.css.Selector((sel, namespaces[i]))
92
                self.assertEqual(result, s.selectorText)
93

    
94
        # add to CSSStyleSheet
95
        sheet = cssutils.css.CSSStyleSheet()
96
        sheet.cssText = '@namespace p "u"; a { color: green }'
97

    
98
        r = sheet.cssRules[1]
99

    
100
        self.assertEqual(r.selectorText, u'a')
101

    
102
        # add default namespace
103
        sheet.namespaces[''] = 'a';
104
        self.assertEqual(r.selectorText, u'|a')
105

    
106
        del sheet.namespaces[''];
107
        self.assertEqual(r.selectorText, u'a')
108

    
109
#        r.selectorList.append('a')
110
#        self.assertEqual(r.selectorText, u'|a, a')
111
#        r.selectorList.append('*|a')
112
#        self.assertEqual(r.selectorText, u'|a, a, *|a')
113

    
114
    def test_default_namespace(self):
115
        "Selector.namespaces default"
116
        css = '''@namespace "default";
117
                a[att] { color:green; }
118
        '''
119
        sheet = cssutils.css.CSSStyleSheet()
120
        sheet.cssText = css
121
        self.assertEqual(sheet.cssText,
122
                         u'@namespace "default";\na[att] {\n    color: green\n    }'.encode())
123
        # use a prefix for default namespace, does not goes for atts!
124
        sheet.namespaces['p'] = 'default'
125
        self.assertEqual(sheet.cssText,
126
                         u'@namespace p "default";\np|a[att] {\n    color: green\n    }'.encode())
127

    
128
    def test_parent(self):
129
        "Selector.parent"
130
        sl = cssutils.css.SelectorList('a, b')
131
        for sel in sl:
132
            self.assertEqual(sl, sel.parent)
133

    
134
        newsel = cssutils.css.Selector('x')
135
        sl.append(newsel)
136
        self.assertEqual(sl, newsel.parent)
137

    
138
        newsel = cssutils.css.Selector('y')
139
        sl.appendSelector(newsel)
140
        self.assertEqual(sl, newsel.parent)
141

    
142
    def test_selectorText(self):
143
        "Selector.selectorText"
144
        tests = {
145
            # combinators
146
            u'a+b>c~e f': u'a + b > c ~ e f',
147
            u'a  +  b  >  c  ~  e   f': u'a + b > c ~ e f',
148
            u'a+b': u'a + b',
149
            u'a  +  b': 'a + b',
150
            u'a\n  +\t  b': 'a + b',
151
            u'a~b': u'a ~ b',
152
            u'a b': None,
153
            u'a   b': 'a b',
154
            u'a\nb': 'a b',
155
            u'a\tb': 'a b',
156
            u'a   #b': 'a #b',
157
            u'a   .b': 'a .b',
158
            u'a * b': None,
159
            # >
160
            u'a>b': u'a > b',
161
            u'a> b': 'a > b',
162
            u'a >b': 'a > b',
163
            u'a > b': 'a > b',
164
            # +
165
            u'a+b': u'a + b',
166
            u'a+ b': 'a + b',
167
            u'a +b': 'a + b',
168
            u'a + b': 'a + b',
169
            # ~
170
            u'a~b': u'a ~ b',
171
            u'a~ b': 'a ~ b',
172
            u'a ~b': 'a ~ b',
173
            u'a ~ b': 'a ~ b',
174

    
175
            # type selector
176
            u'a': None,
177
            u'h1-a_x__--': None,
178
            u'a-a': None,
179
            u'a_a': None,
180
            u'-a': None,
181
            u'_': None,
182
            u'-_': None,
183
            ur'-\72': u'-r',
184
            #ur'\25': u'%', # TODO: should be escaped!
185
            u'.a a': None,
186
            u'a1': None,
187
            u'a1-1': None,
188
            u'.a1-1': None,
189

    
190
            # universal
191
            u'*': None,
192
            u'*/*x*/': None,
193
            u'* /*x*/': None,
194
            u'*:hover': None,
195
            u'* :hover': None,
196
            u'*:lang(fr)': None,
197
            u'* :lang(fr)': None,
198
            u'*::first-line': None,
199
            u'* ::first-line': None,
200
            u'*[lang=fr]': None,
201
            u'[lang=fr]': None,
202

    
203
            # HASH
204
            u'''#a''': None,
205
            u'''#a1''': None,
206
            u'''#1a''': None, # valid to grammar but not for HTML
207
            u'''#1''': None, # valid to grammar but not for HTML
208
            u'''a#b''': None,
209
            u'''a #b''': None,
210
            u'''a#b.c''': None,
211
            u'''a.c#b''': None,
212
            u'''a #b.c''': None,
213
            u'''a .c#b''': None,
214

    
215
            # class
216
            u'ab': 'ab',
217
            u'a.b': None,
218
            u'a.b.c': None,
219
            u'.a1._1': None,
220

    
221
            # attrib
222
            u'''[x]''': None,
223
            u'''*[x]''': None,
224
            u'''a[x]''': None,
225
            u'''a[ x]''': 'a[x]',
226
            u'''a[x ]''': 'a[x]',
227
            u'''a [x]''': 'a [x]',
228
            u'''* [x]''': None, # is really * *[x]
229

    
230
            u'''a[x="1"]''': None,
231
            u'''a[x ="1"]''': 'a[x="1"]',
232
            u'''a[x= "1"]''': 'a[x="1"]',
233
            u'''a[x = "1"]''': 'a[x="1"]',
234
            u'''a[ x = "1"]''': 'a[x="1"]',
235
            u'''a[x = "1" ]''': 'a[x="1"]',
236
            u'''a[ x = "1" ]''': 'a[x="1"]',
237
            u'''a [ x = "1" ]''': 'a [x="1"]',
238

    
239
            u'''a[x~=a1]''': None,
240
            u'''a[x ~=a1]''': 'a[x~=a1]',
241
            u'''a[x~= a1]''': 'a[x~=a1]',
242
            u'''a[x ~= a1]''': 'a[x~=a1]',
243
            u'''a[ x ~= a1]''': 'a[x~=a1]',
244
            u'''a[x ~= a1 ]''': 'a[x~=a1]',
245
            u'''a[ x ~= a1 ]''': 'a[x~=a1]',
246
            u'''a [ x ~= a1 ]''': 'a [x~=a1]', # same as next!
247
            u'''a *[ x ~= a1 ]''': 'a *[x~=a1]',
248

    
249
            u'''a[x|=en]''': None,
250
            u'''a[x|= en]''': 'a[x|=en]',
251
            u'''a[x |=en]''': 'a[x|=en]',
252
            u'''a[x |= en]''': 'a[x|=en]',
253
            u'''a[ x |= en]''': 'a[x|=en]',
254
            u'''a[x |= en ]''': 'a[x|=en]',
255
            u'''a[ x |= en]''': 'a[x|=en]',
256
            u'''a [ x |= en]''': 'a [x|=en]',
257
            # CSS3
258
            u'''a[x^=en]''': None,
259
            u'''a[x$=en]''': None,
260
            u'''a[x*=en]''': None,
261

    
262
            u'''a[/*1*/x/*2*/]''': None,
263
            u'''a[/*1*/x/*2*/=/*3*/a/*4*/]''': None,
264
            u'''a[/*1*/x/*2*/~=/*3*/a/*4*/]''': None,
265
            u'''a[/*1*/x/*2*/|=/*3*/a/*4*/]''': None,
266

    
267
            # pseudo-elements
268
            u'a x:first-line': None,
269
            u'a x:first-letter': None,
270
            u'a x:before': None,
271
            u'a x:after': None,
272
            u'a x::selection': None,
273
            u'a:hover+b:hover>c:hover~e:hover f:hover':
274
                u'a:hover + b:hover > c:hover ~ e:hover f:hover',
275
            u'a:hover  +  b:hover  >  c:hover  ~  e:hover   f:hover':
276
                u'a:hover + b:hover > c:hover ~ e:hover f:hover',
277
            u'a::selection+b::selection>c::selection~e::selection f::selection':
278
                u'a::selection + b::selection > c::selection ~ e::selection f::selection',
279
            u'a::selection  +  b::selection  >  c::selection  ~  e::selection   f::selection':
280
                u'a::selection + b::selection > c::selection ~ e::selection f::selection',
281

    
282
            u'x:lang(de) y': None,
283
            u'x:nth-child(odd) y': None,
284
            # functional pseudo
285
            u'x:func(a + b-2px22.3"s"i)': None,
286
            u'x:func(1 + 1)': None,
287
            u'x:func(1+1)': u'x:func(1+1)',
288
            u'x:func(1   +   1)': u'x:func(1 + 1)',
289
            u'x:func(1-1)': u'x:func(1-1)',
290
            u'x:func(1  -  1)': u'x:func(1 -1)', # TODO: FIX!
291
            u'x:func(a-1)': u'x:func(a-1)',
292
            u'x:func(a -1px)': u'x:func(a -1px)',
293
            u'x:func(1px)': None,
294
            u'x:func(23.4)': None,
295
            u'x:func("s")': None,
296
            u'x:func(i)': None,
297

    
298
            # negation
299
            u':not(y)': None,
300
            u':not(   y  \t\n)': u':not(y)',
301
            u'*:not(y)': None,
302
            u'x:not(y)': None,
303
            u'.x:not(y)': None,
304
            u':not(*)': None,
305
            u':not(#a)': None,
306
            u':not(.a)': None,
307
            u':not([a])': None,
308
            u':not(:first-letter)': None,
309
            u':not(::first-letter)': None,
310

    
311
            # escapes
312
            ur'\74\72 td': 'trtd',
313
            ur'\74\72  td': 'tr td',
314
            ur'\74\000072 td': 'trtd',
315
            ur'\74\000072  td': 'tr td',
316

    
317
            # comments
318
            u'a/**/ b': None,
319
            u'a /**/b': None,
320
            u'a /**/ b': None,
321
            u'a  /**/ b': u'a /**/ b',
322
            u'a /**/  b': u'a /**/ b',
323

    
324
            # namespaces
325
            u'|e': None,
326
            u'*|e': None,
327
            u'*|*': None,
328
            (u'p|*', (('p', 'uri'),)): u'p|*',
329
            (u'p|e', (('p', 'uri'),)): u'p|e',
330
            (u'-a_x12|e', (('-a_x12', 'uri'),)): u'-a_x12|e',
331
            (u'*|b[p|a]', (('p', 'uri'),)): '*|b[p|a]',
332

    
333
            # case
334
            u'elemenT.clasS#iD[atT="valuE"]:noT(x)::firsT-linE':
335
                u'elemenT.clasS#iD[atT="valuE"]:not(x)::first-line'
336
            }
337
        # do not parse as not complete
338
        self.do_equal_r(tests, att='selectorText')
339

    
340
        tests = {
341
            u'x|a': xml.dom.NamespaceErr,
342
            (u'p|*', (('x', 'uri'),)): xml.dom.NamespaceErr,
343

    
344
            u'': xml.dom.SyntaxErr,
345
            u'1': xml.dom.SyntaxErr,
346
            u'-1': xml.dom.SyntaxErr,
347
            u'a*b': xml.dom.SyntaxErr,
348
            u'a *b': xml.dom.SyntaxErr,
349
            u'a* b': xml.dom.SyntaxErr,
350
            u'a/**/b': xml.dom.SyntaxErr,
351

    
352
            u'#': xml.dom.SyntaxErr,
353
            u'|': xml.dom.SyntaxErr,
354

    
355
            u':': xml.dom.SyntaxErr,
356
            u'::': xml.dom.SyntaxErr,
357
            u': a': xml.dom.SyntaxErr,
358
            u':: a': xml.dom.SyntaxErr,
359
            u':a()': xml.dom.SyntaxErr, # no value
360
            u'::a()': xml.dom.SyntaxErr, # no value
361
            u':::a': xml.dom.SyntaxErr,
362
            u':1': xml.dom.SyntaxErr,
363

    
364
            u'#.x': xml.dom.SyntaxErr,
365
            u'.': xml.dom.SyntaxErr,
366
            u'.1': xml.dom.SyntaxErr,
367
            u'.a.1': xml.dom.SyntaxErr,
368

    
369
            u'[a': xml.dom.SyntaxErr,
370
            u'a]': xml.dom.SyntaxErr,
371
            u'[a b]': xml.dom.SyntaxErr,
372
            u'[=b]': xml.dom.SyntaxErr,
373
            u'[a=]': xml.dom.SyntaxErr,
374
            u'[a|=]': xml.dom.SyntaxErr,
375
            u'[a~=]': xml.dom.SyntaxErr,
376
            u'[a=1]': xml.dom.SyntaxErr,
377

    
378
            u'a +': xml.dom.SyntaxErr,
379
            u'a >': xml.dom.SyntaxErr,
380
            u'a ++ b': xml.dom.SyntaxErr,
381
            u'a + > b': xml.dom.SyntaxErr,
382

    
383
            # functional pseudo
384
            u'*:lang(': xml.dom.SyntaxErr,
385
            u'*:lang()': xml.dom.SyntaxErr, # no arg
386

    
387
            # negation
388
            u'not(x)': xml.dom.SyntaxErr, # no valid function
389
            u':not()': xml.dom.SyntaxErr, # no arg
390
            u':not(x': xml.dom.SyntaxErr, # no )
391
            u':not(-': xml.dom.SyntaxErr, # not allowed
392
            u':not(+': xml.dom.SyntaxErr, # not allowed
393

    
394
            # only one selector!
395
            u',': xml.dom.InvalidModificationErr,
396
            u',a': xml.dom.InvalidModificationErr,
397
            u'a,': xml.dom.InvalidModificationErr,
398

    
399
            # @
400
            u'p @here': xml.dom.SyntaxErr, # not allowed
401

    
402
            }
403
        # only set as not complete
404
        self.do_raise_r(tests, att='_setSelectorText')
405

    
406
    def test_specificity(self):
407
        "Selector.specificity"
408
        selector = cssutils.css.Selector()
409

    
410
        # readonly
411
        def _set(): selector.specificity = 1
412
        self.assertRaisesMsg(AttributeError, "can't set attribute", _set)
413

    
414
        tests = {
415
            u'*': (0,0,0,0),
416
            u'li': (0,0,0,1),
417
            u'li:first-line': (0,0,0,2),
418
            u'ul li': (0,0,0,2),
419
            u'ul ol+li': (0,0,0,3),
420
            u'h1 + *[rel=up]': (0,0,1,1),
421
            u'ul ol li.red': (0,0,1,3),
422
            u'li.red.level': (0,0,2,1),
423
            u'#x34y': (0,1,0,0),
424

    
425
            u'UL OL LI.red': (0,0,1,3),
426
            u'LI.red.level': (0,0,2,1),
427
            u'#s12:not(FOO)': (0,1,0,1),
428
            u'button:not([DISABLED])': (0,0,1,1), #?
429
            u'*:not(FOO)': (0,0,0,1),
430

    
431
            # elements
432
            u'a+b': (0,0,0,2),
433
            u'a>b': (0,0,0,2),
434
            u'a b': (0,0,0,2),
435
            u'* a': (0,0,0,1),
436
            u'a *': (0,0,0,1),
437
            u'a * b': (0,0,0,2),
438

    
439
            u'a:hover': (0,0,0,1),
440

    
441
            u'a:first-line': (0,0,0,2),
442
            u'a:first-letter': (0,0,0,2),
443
            u'a:before': (0,0,0,2),
444
            u'a:after': (0,0,0,2),
445

    
446
            # classes and attributes
447
            u'.a': (0,0,1,0),
448
            u'*.a': (0,0,1,0),
449
            u'a.a': (0,0,1,1),
450
            u'.a.a': (0,0,2,0), # IE<7 False (0,0,1,0)
451
            u'a.a.a': (0,0,2,1),
452
            u'.a.b': (0,0,2,0),
453
            u'a.a.b': (0,0,2,1),
454
            u'.a .a': (0,0,2,0),
455
            u'*[x]': (0,0,1,0),
456
            u'*[x]': (0,0,1,0),
457
            u'*[x]': (0,0,1,0),
458
            u'*[x=a]': (0,0,1,0),
459
            u'*[x~=a]': (0,0,1,0),
460
            u'*[x|=a]': (0,0,1,0),
461
            u'*[x^=a]': (0,0,1,0),
462
            u'*[x*=a]': (0,0,1,0),
463
            u'*[x$=a]': (0,0,1,0),
464
            u'*[x][y]': (0,0,2,0),
465

    
466
            # ids
467
            u'#a': (0,1,0,0),
468
            u'*#a': (0,1,0,0),
469
            u'x#a': (0,1,0,1),
470
            u'.x#a': (0,1,1,0),
471
            u'a.x#a': (0,1,1,1),
472
            u'#a#a': (0,2,0,0), # e.g. html:id + xml:id
473
            u'#a#b': (0,2,0,0),
474
            u'#a #b': (0,2,0,0),
475
            }
476
        for text in tests:
477
            selector.selectorText = text
478
            self.assertEqual(tests[text], selector.specificity)
479

    
480
    def test_reprANDstr(self):
481
        "Selector.__repr__(), .__str__()"
482
        sel=u'a + b'
483

    
484
        s = cssutils.css.Selector(selectorText=sel)
485

    
486
        self.assertTrue(sel in str(s))
487

    
488
        s2 = eval(repr(s))
489
        self.assertTrue(isinstance(s2, s.__class__))
490
        self.assertTrue(sel == s2.selectorText)
491

    
492

    
493
if __name__ == '__main__':
494
    import unittest
495
    unittest.main()