Package cssutils :: Package tests :: Module test_selector
[hide private]
[frames] | no frames]

Source Code for Module cssutils.tests.test_selector

  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  __author__ = '$LastChangedBy: cthedot $' 
 10  __date__ = '$LastChangedDate: 2008-02-02 23:53:54 +0100 (Sa, 02 Feb 2008) $' 
 11  __version__ = '$LastChangedRevision: 975 $' 
 12   
 13  import xml.dom 
 14  import basetest 
 15  import cssutils 
 16   
17 -class SelectorTestCase(basetest.BaseTestCase):
18
19 - def setUp(self):
20 self.r = cssutils.css.Selector('*')
21
22 - def test_init(self):
23 "Selector.__init__()" 24 s = cssutils.css.Selector('*') 25 self.assertEqual((None, '*'), s.element) 26 self.assertEqual({}, s._namespaces.namespaces) 27 self.assertEqual(None, s.parentList) 28 self.assertEqual('*', s.selectorText) 29 self.assertEqual((0,0,0,0), s.specificity) 30 self.assertEqual(True, s.wellformed) 31 32 s = cssutils.css.Selector(('p|b', {'p': 'URI'}) ) 33 self.assertEqual(('URI', 'b'), s.element) 34 self.assertEqual({'p': 'URI'}, s._namespaces.namespaces) 35 self.assertEqual(None, s.parentList) 36 self.assertEqual('p|b', s.selectorText) 37 self.assertEqual((0,0,0,1), s.specificity) 38 self.assertEqual(True, s.wellformed) 39 40 self.assertRaisesEx(xml.dom.NamespaceErr, cssutils.css.Selector, 'p|b')
41
42 - def test_element(self):
43 "Selector.element (TODO: RESOLVE)" 44 tests = { 45 '*': (None, '*'), 46 'x': (None, 'x'), 47 '\\x': (None, '\\x'), 48 '|x': (u'', 'x'), 49 '*|x': (cssutils._ANYNS, 'x'), 50 'ex|x': (u'example', 'x'), 51 'a x': (None, 'x'), 52 'a+x': (None, 'x'), 53 'a>x': (None, 'x'), 54 'a~x': (None, 'x'), 55 'a+b~c x': (None, 'x'), 56 'x[href]': (None, 'x'), 57 'x[href="123"]': (None, 'x'), 58 'x:hover': (None, 'x'), 59 'x:first-letter': (None, 'x'), # TODO: Really? 60 'x::first-line': (None, 'x'), # TODO: Really? 61 'x:not(href)': (None, 'x'), # TODO: Really? 62 63 '#id': None, 64 '.c': None, 65 'x#id': (None, 'x'), 66 'x.c': (None, 'x') 67 } 68 for test, ele in tests.items(): 69 s = cssutils.css.Selector((test,{'ex': 'example'})) 70 self.assertEqual(ele, s.element)
71
72 - def test_namespaces(self):
73 "Selector.namespaces" 74 namespaces = [ 75 {'p': 'other'}, # no default 76 {'': 'default', 'p': 'other'}, # with default 77 {'': 'default', 'p': 'default' } # same default 78 ] 79 tests = { 80 # selector: with default, no default, same default 81 '*': ('*', '|*', '|*'), 82 'x': ('x', '|x', '|x'), 83 '|*': ('|*', '|*', '|*'), 84 '|x': ('|x', '|x', '|x'), 85 '*|*': ('*', '*', '*'), 86 '*|x': ('x', 'x', 'x'), 87 'p|*': ('p|*', 'p|*', '|*'), 88 'p|x': ('p|x', 'p|x', '|x'), 89 'x[a][|a][*|a][p|a]': ('x[a][|a][a][p|a]', 90 '|x[|a][|a][*|a][p|a]', 91 '|x[|a][|a][*|a][|a]') 92 } 93 for sel, exp in tests.items(): 94 for i, result in enumerate(exp): 95 s = cssutils.css.Selector((sel, namespaces[i])) 96 self.assertEqual(result, s.selectorText) 97 98 # add to CSSStyleSheet 99 sheet = cssutils.css.CSSStyleSheet() 100 sheet.cssText = '@namespace p "u"; p|x { color: green }'
101
102 - def test_parentList(self):
103 "Selector.parentList" 104 sl = cssutils.css.SelectorList('a, b') 105 for sel in sl: 106 self.assertEqual(sl, sel.parentList) 107 108 newsel = cssutils.css.Selector('x') 109 sl.append(newsel) 110 self.assertEqual(sl, newsel.parentList) 111 112 newsel = cssutils.css.Selector('y') 113 sl.appendSelector(newsel) 114 self.assertEqual(sl, newsel.parentList)
115
116 - def test_selectorText(self):
117 "Selector.selectorText" 118 tests = { 119 # combinators 120 u'a+b>c~e f': u'a + b > c ~ e f', 121 u'a+b': u'a + b', 122 u'a + b': 'a + b', 123 u'a\n +\t b': 'a + b', 124 u'a~b': u'a ~ b', 125 u'a b': None, 126 u'a b': 'a b', 127 u'a\nb': 'a b', 128 u'a\tb': 'a b', 129 u'a #b': 'a #b', 130 u'a .b': 'a .b', 131 u'a * b': None, 132 # > 133 u'a>b': u'a > b', 134 u'a> b': 'a > b', 135 u'a >b': 'a > b', 136 u'a > b': 'a > b', 137 # + 138 u'a+b': u'a + b', 139 u'a+ b': 'a + b', 140 u'a +b': 'a + b', 141 u'a + b': 'a + b', 142 # ~ 143 u'a~b': u'a ~ b', 144 u'a~ b': 'a ~ b', 145 u'a ~b': 'a ~ b', 146 u'a ~ b': 'a ~ b', 147 148 # type selector 149 u'a': None, 150 u'h1-a_x__--': None, 151 u'a-a': None, 152 u'a_a': None, 153 u'-a': None, 154 u'_': None, 155 u'-_': None, 156 ur'-\72': u'-r', 157 #ur'\25': u'%', # TODO: should be escaped! 158 u'.a a': None, 159 u'a1': None, 160 u'a1-1': None, 161 u'.a1-1': None, 162 163 # universal 164 u'*': None, 165 u'*/*x*/': None, 166 u'* /*x*/': None, 167 u'*:hover': None, 168 u'* :hover': None, 169 u'*:lang(fr)': None, 170 u'* :lang(fr)': None, 171 u'*::first-line': None, 172 u'* ::first-line': None, 173 u'*[lang=fr]': None, 174 u'[lang=fr]': None, 175 176 # HASH 177 u'''#a''': None, 178 u'''#a1''': None, 179 u'''#1a''': None, # valid to grammar but not for HTML 180 u'''#1''': None, # valid to grammar but not for HTML 181 u'''a#b''': None, 182 u'''a #b''': None, 183 u'''a#b.c''': None, 184 u'''a.c#b''': None, 185 u'''a #b.c''': None, 186 u'''a .c#b''': None, 187 188 # class 189 u'ab': 'ab', 190 u'a.b': None, 191 u'a.b.c': None, 192 u'.a1._1': None, 193 194 # attrib 195 u'''[x]''': None, 196 u'''*[x]''': None, 197 u'''a[x]''': None, 198 u'''a[ x]''': 'a[x]', 199 u'''a[x ]''': 'a[x]', 200 u'''a [x]''': 'a [x]', 201 u'''* [x]''': None, # is really * *[x] 202 203 u'''a[x="1"]''': None, 204 u'''a[x ="1"]''': 'a[x="1"]', 205 u'''a[x= "1"]''': 'a[x="1"]', 206 u'''a[x = "1"]''': 'a[x="1"]', 207 u'''a[ x = "1"]''': 'a[x="1"]', 208 u'''a[x = "1" ]''': 'a[x="1"]', 209 u'''a[ x = "1" ]''': 'a[x="1"]', 210 u'''a [ x = "1" ]''': 'a [x="1"]', 211 212 u'''a[x~=a1]''': None, 213 u'''a[x ~=a1]''': 'a[x~=a1]', 214 u'''a[x~= a1]''': 'a[x~=a1]', 215 u'''a[x ~= a1]''': 'a[x~=a1]', 216 u'''a[ x ~= a1]''': 'a[x~=a1]', 217 u'''a[x ~= a1 ]''': 'a[x~=a1]', 218 u'''a[ x ~= a1 ]''': 'a[x~=a1]', 219 u'''a [ x ~= a1 ]''': 'a [x~=a1]', # same as next! 220 u'''a *[ x ~= a1 ]''': 'a *[x~=a1]', 221 222 u'''a[x|=en]''': None, 223 u'''a[x|= en]''': 'a[x|=en]', 224 u'''a[x |=en]''': 'a[x|=en]', 225 u'''a[x |= en]''': 'a[x|=en]', 226 u'''a[ x |= en]''': 'a[x|=en]', 227 u'''a[x |= en ]''': 'a[x|=en]', 228 u'''a[ x |= en]''': 'a[x|=en]', 229 u'''a [ x |= en]''': 'a [x|=en]', 230 # CSS3 231 u'''a[x^=en]''': None, 232 u'''a[x$=en]''': None, 233 u'''a[x*=en]''': None, 234 235 u'''a[/*1*/x/*2*/]''': None, 236 u'''a[/*1*/x/*2*/=/*3*/a/*4*/]''': None, 237 u'''a[/*1*/x/*2*/~=/*3*/a/*4*/]''': None, 238 u'''a[/*1*/x/*2*/|=/*3*/a/*4*/]''': None, 239 240 # pseudo-elements 241 u'a x:first-line': None, 242 u'a x:first-letter': None, 243 u'a x:before': None, 244 u'a x:after': None, 245 u'a x::selection': None, 246 247 u'x:lang(de) y': None, 248 u'x:nth-child(odd) y': None, 249 # functional pseudo 250 u'x:func(+-2px22.3"s"i)': None, 251 u'x:func(+)': None, 252 u'x:func(1px)': None, 253 u'x:func(23.4)': None, 254 u'x:func("s")': None, 255 u'x:func(i)': None, 256 257 # negation 258 u':not(y)': None, 259 u':not( y \t\n)': u':not(y)', 260 u'*:not(y)': None, 261 u'x:not(y)': None, 262 u'.x:not(y)': None, 263 u':not(*)': None, 264 u':not(#a)': None, 265 u':not(.a)': None, 266 u':not([a])': None, 267 u':not(:first-letter)': None, 268 u':not(::first-letter)': None, 269 270 # escapes 271 ur'\74\72 td': 'trtd', 272 ur'\74\72 td': 'tr td', 273 ur'\74\000072 td': 'trtd', 274 ur'\74\000072 td': 'tr td', 275 276 # comments 277 u'a/**/ b': None, 278 u'a /**/b': None, 279 u'a /**/ b': None, 280 u'a /**/ b': u'a /**/ b', 281 u'a /**/ b': u'a /**/ b', 282 283 # namespaces 284 u'|e': u'|e', 285 u'*|e': 'e', 286 u'*|*': u'*', 287 (u'p|*', (('p', 'uri'),)): u'p|*', 288 (u'p|e', (('p', 'uri'),)): u'p|e', 289 (u'-a_x12|e', (('-a_x12', 'uri'),)): u'-a_x12|e', 290 (u'*|b[p|a]', (('p', 'uri'),)): 'b[p|a]' 291 } 292 # do not parse as not complete 293 self.do_equal_r(tests, att='selectorText') 294 295 tests = { 296 u'x|a': xml.dom.NamespaceErr, 297 (u'p|*', (('x', 'uri'),)): xml.dom.NamespaceErr, 298 299 u'': xml.dom.SyntaxErr, 300 u'1': xml.dom.SyntaxErr, 301 u'-1': xml.dom.SyntaxErr, 302 u'a*b': xml.dom.SyntaxErr, 303 u'a *b': xml.dom.SyntaxErr, 304 u'a* b': xml.dom.SyntaxErr, 305 u'a/**/b': xml.dom.SyntaxErr, 306 307 u'#': xml.dom.SyntaxErr, 308 u'|': xml.dom.SyntaxErr, 309 310 u':': xml.dom.SyntaxErr, 311 u'::': xml.dom.SyntaxErr, 312 u': a': xml.dom.SyntaxErr, 313 u':: a': xml.dom.SyntaxErr, 314 u':a()': xml.dom.SyntaxErr, # no value 315 u'::a()': xml.dom.SyntaxErr, # no value 316 u':::a': xml.dom.SyntaxErr, 317 u':1': xml.dom.SyntaxErr, 318 319 u'#.x': xml.dom.SyntaxErr, 320 u'.': xml.dom.SyntaxErr, 321 u'.1': xml.dom.SyntaxErr, 322 u'.a.1': xml.dom.SyntaxErr, 323 324 u'[a': xml.dom.SyntaxErr, 325 u'a]': xml.dom.SyntaxErr, 326 u'[a b]': xml.dom.SyntaxErr, 327 u'[=b]': xml.dom.SyntaxErr, 328 u'[a=]': xml.dom.SyntaxErr, 329 u'[a|=]': xml.dom.SyntaxErr, 330 u'[a~=]': xml.dom.SyntaxErr, 331 u'[a=1]': xml.dom.SyntaxErr, 332 333 u'a +': xml.dom.SyntaxErr, 334 u'a >': xml.dom.SyntaxErr, 335 u'a ++ b': xml.dom.SyntaxErr, 336 u'a + > b': xml.dom.SyntaxErr, 337 338 # functional pseudo 339 u'*:lang(': xml.dom.SyntaxErr, 340 u'*:lang()': xml.dom.SyntaxErr, # no arg 341 342 # negation 343 u'not(x)': xml.dom.SyntaxErr, # no valid function 344 u':not()': xml.dom.SyntaxErr, # no arg 345 u':not(x': xml.dom.SyntaxErr, # no ) 346 u':not(-': xml.dom.SyntaxErr, # not allowed 347 u':not(+': xml.dom.SyntaxErr, # not allowed 348 349 # only one selector! 350 u',': xml.dom.InvalidModificationErr, 351 u',a': xml.dom.InvalidModificationErr, 352 u'a,': xml.dom.InvalidModificationErr, 353 } 354 # only set as not complete 355 self.do_raise_r(tests, att='_setSelectorText')
356
357 - def test_specificity(self):
358 "Selector.specificity" 359 selector = cssutils.css.Selector() 360 361 # readonly 362 def _set(): selector.specificity = 1 363 self.assertRaisesMsg(AttributeError, "can't set attribute", _set) 364 365 tests = { 366 u'*': (0,0,0,0), 367 u'li': (0,0,0,1), 368 u'li:first-line': (0,0,0,2), 369 u'ul li': (0,0,0,2), 370 u'ul ol+li': (0,0,0,3), 371 u'h1 + *[rel=up]': (0,0,1,1), 372 u'ul ol li.red': (0,0,1,3), 373 u'li.red.level': (0,0,2,1), 374 u'#x34y': (0,1,0,0), 375 376 u'UL OL LI.red': (0,0,1,3), 377 u'LI.red.level': (0,0,2,1), 378 u'#s12:not(FOO)': (0,1,0,1), 379 u'button:not([DISABLED])': (0,0,1,1), #? 380 u'*:not(FOO)': (0,0,0,1), 381 382 # elements 383 u'a+b': (0,0,0,2), 384 u'a>b': (0,0,0,2), 385 u'a b': (0,0,0,2), 386 u'* a': (0,0,0,1), 387 u'a *': (0,0,0,1), 388 u'a * b': (0,0,0,2), 389 390 u'a:hover': (0,0,0,1), 391 392 u'a:first-line': (0,0,0,2), 393 u'a:first-letter': (0,0,0,2), 394 u'a:before': (0,0,0,2), 395 u'a:after': (0,0,0,2), 396 397 # classes and attributes 398 u'.a': (0,0,1,0), 399 u'*.a': (0,0,1,0), 400 u'a.a': (0,0,1,1), 401 u'.a.a': (0,0,2,0), # IE<7 False (0,0,1,0) 402 u'a.a.a': (0,0,2,1), 403 u'.a.b': (0,0,2,0), 404 u'a.a.b': (0,0,2,1), 405 u'.a .a': (0,0,2,0), 406 u'*[x]': (0,0,1,0), 407 u'*[x]': (0,0,1,0), 408 u'*[x]': (0,0,1,0), 409 u'*[x=a]': (0,0,1,0), 410 u'*[x~=a]': (0,0,1,0), 411 u'*[x|=a]': (0,0,1,0), 412 u'*[x^=a]': (0,0,1,0), 413 u'*[x*=a]': (0,0,1,0), 414 u'*[x$=a]': (0,0,1,0), 415 u'*[x][y]': (0,0,2,0), 416 417 # ids 418 u'#a': (0,1,0,0), 419 u'*#a': (0,1,0,0), 420 u'x#a': (0,1,0,1), 421 u'.x#a': (0,1,1,0), 422 u'a.x#a': (0,1,1,1), 423 u'#a#a': (0,2,0,0), # e.g. html:id + xml:id 424 u'#a#b': (0,2,0,0), 425 u'#a #b': (0,2,0,0), 426 } 427 for text in tests: 428 selector.selectorText = text 429 self.assertEqual(tests[text], selector.specificity)
430
431 - def test_reprANDstr(self):
432 "Selector.__repr__(), .__str__()" 433 sel=u'a + b' 434 435 s = cssutils.css.Selector(selectorText=sel) 436 437 self.assert_(sel in str(s)) 438 439 s2 = eval(repr(s)) 440 self.assert_(isinstance(s2, s.__class__)) 441 self.assert_(sel == s2.selectorText)
442 443 444 if __name__ == '__main__': 445 import unittest 446 unittest.main() 447