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() |