1
2 """
3 tests for css.CSSStyleSheet
4 """
5 __author__ = '$LastChangedBy: cthedot $'
6 __date__ = '$LastChangedDate: 2008-02-22 19:03:20 +0100 (Fr, 22 Feb 2008) $'
7 __version__ = '$LastChangedRevision: 1070 $'
8
9 import xml.dom
10 import basetest
11 import cssutils.css
12
14
20
22 "CSSStyleSheet.__init__()"
23 self.assertEqual('text/css', self.s.type)
24 self.assertEqual(False, self.s._readonly)
25 self.assertEqual([], self.s.cssRules)
26 self.assertEqual(False, self.s.disabled)
27 self.assertEqual(None, self.s.href)
28 self.assertEqual(None, self.s.media)
29 self.assertEqual(None, self.s.ownerNode)
30 self.assertEqual(None, self.s.parentStyleSheet)
31 self.assertEqual(u'', self.s.title)
32
43
44 - def test_cssText(self):
45 "CSSStyleSheet.cssText"
46 tests = {
47 u'': None,
48
49 u'@charset "ascii";\n@import "x";': None,
50 u'@charset "ascii";\n@media all {}': u'@charset "ascii";',
51 u'@charset "ascii";\n@x;': None,
52 u'@charset "ascii";\na {\n x: 1\n }': None,
53
54 u'@x;\n@import "x";': None,
55 u'@import "x";\n@import "y";': None,
56 u'@import "x";\n@media all {}': u'@import "x";',
57 u'@import "x";\n@x;': None,
58 u'@import "x";\na {\n x: 1\n }': None,
59
60 u'@x;\n@namespace a "x";': None,
61 u'@namespace a "x";\n@namespace b "y";': None,
62 u'@import "x";\n@namespace a "x";\n@media all {}':
63 u'@import "x";\n@namespace a "x";',
64 u'@namespace a "x";\n@x;': None,
65 u'@namespace a "x";\na {\n x: 1\n }': None,
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 }
83 self.do_equal_r(tests)
84 self.do_equal_p(tests)
85
86 s = cssutils.css.CSSStyleSheet()
87 s.cssText = u'''@charset "ascii";@import "x";@namespace a "x";
88 @media all {/*1*/}@page {margin: 0}a {\n x: 1\n }@unknown;/*comment*/'''
89 for r in s.cssRules:
90 self.assertEqual(s, r.parentStyleSheet)
91
93 "CSSStyleSheet.cssText HierarchyRequestErr"
94 tests = {
95
96 u' @charset "utf-8";': xml.dom.HierarchyRequestErr,
97 u'@charset "ascii";@charset "ascii";': xml.dom.HierarchyRequestErr, u'/*c*/@charset "ascii";': xml.dom.HierarchyRequestErr,
98 u'@import "x"; @charset "ascii";': xml.dom.HierarchyRequestErr,
99 u'@namespace a "x"; @charset "ascii";': xml.dom.HierarchyRequestErr,
100 u'@media all {} @charset "ascii";': xml.dom.HierarchyRequestErr,
101 u'@page {} @charset "ascii";': xml.dom.HierarchyRequestErr,
102 u'a {} @charset "ascii";': xml.dom.HierarchyRequestErr,
103
104
105 u'@namespace a "x"; @import "x";': xml.dom.HierarchyRequestErr,
106 u'@media all {} @import "x";': xml.dom.HierarchyRequestErr,
107 u'@page {} @import "x";': xml.dom.HierarchyRequestErr,
108 u'a {} @import "x";': xml.dom.HierarchyRequestErr,
109
110
111 u'@media all {} @namespace a "x";': xml.dom.HierarchyRequestErr,
112 u'@page {} @namespace a "x";': xml.dom.HierarchyRequestErr,
113 u'a {} @namespace a "x";': xml.dom.HierarchyRequestErr,
114 }
115 self.do_raise_r(tests)
116 self.do_raise_p(tests)
117
119 """CSSStyleSheet.cssText SyntaxErr
120
121 for single {, } or ;
122 """
123 tests = {
124 u'{': xml.dom.SyntaxErr,
125 u'}': xml.dom.SyntaxErr,
126 u';': xml.dom.SyntaxErr,
127 u'@charset "ascii";{': xml.dom.SyntaxErr,
128 u'@charset "ascii";}': xml.dom.SyntaxErr,
129 u'@charset "ascii";;': xml.dom.SyntaxErr,
130 }
131 self.do_raise_r(tests)
132 self.do_raise_p(tests)
133
135 "CSSStyleSheet.encoding"
136 self.s.cssText=''
137 self.assertEqual('utf-8', self.s.encoding)
138
139 self.s.encoding = 'ascii'
140 self.assertEqual('ascii', self.s.encoding)
141 self.assertEqual(1, self.s.cssRules.length)
142 self.assertEqual('ascii', self.s.cssRules[0].encoding)
143
144 self.s.encoding = None
145 self.assertEqual('utf-8', self.s.encoding)
146 self.assertEqual(0, self.s.cssRules.length)
147
148 self.s.encoding = 'UTF-8'
149 self.assertEqual('utf-8', self.s.encoding)
150 self.assertEqual(1, self.s.cssRules.length)
151
152 self.assertRaises(xml.dom.SyntaxErr, self.s._setEncoding,
153 'INVALID ENCODING')
154 self.assertEqual('utf-8', self.s.encoding)
155 self.assertEqual(1, self.s.cssRules.length)
156
158 "CSSStyleSheet.namespaces.namespaces"
159
160 s = cssutils.css.CSSStyleSheet()
161 self.assertEqual(0, len(s.namespaces))
162
163 css = u'''@namespace "default";
164 @namespace ex "example";
165 @namespace ex2 "example";
166 ex2|x { top: 0 }'''
167 expcss = u'''@namespace "default";
168 @namespace ex2 "example";
169 ex2|x {
170 top: 0
171 }'''
172 s.cssText = css
173 self.assertEqual(s.cssText, expcss)
174 self.assertEqual(s.namespaces.namespaces,
175 { u'': u'default', u'ex2': u'example'})
176
177
178 self.assertTrue('' in s.namespaces)
179 self.assertTrue('ex2' in s.namespaces)
180 self.assertFalse('NOTSET' in s.namespaces)
181
182 self.assertRaises(xml.dom.NoModificationAllowedErr,
183 s.namespaces.__delitem__, 'ex2')
184 s.namespaces['del'] = 'del'
185 del s.namespaces['del']
186 self.assertRaises(xml.dom.NamespaceErr, s.namespaces.__getitem__, 'del')
187
188 self.assertEquals('default', s.namespaces[''])
189 self.assertEquals('example', s.namespaces['ex2'])
190 self.assertRaises(xml.dom.NamespaceErr, s.namespaces.__getitem__, 'UNSET')
191
192 self.assertEquals(['', 'ex2'], [n for n in s.namespaces])
193
194 self.assertEqual(2, len(s.namespaces))
195
196 self.assertRaises(xml.dom.NoModificationAllowedErr,
197 s.namespaces.__setitem__, 'ex2', 'NEWURI')
198 s.namespaces['n1'] = 'new'
199 self.assertEqual(s.namespaces.namespaces,
200 { u'': u'default', u'ex2': u'example', u'n1': 'new'})
201 s.namespaces['n'] = 'new'
202 self.assertEqual(s.namespaces.namespaces,
203 { u'': u'default', u'ex2': u'example', u'n': 'new'})
204
205 self.assertEquals('', s.namespaces.prefixForNamespaceURI('default'))
206 self.assertEquals('ex2', s.namespaces.prefixForNamespaceURI('example'))
207 self.assertRaises(IndexError,
208 s.namespaces.prefixForNamespaceURI, 'UNSET')
209
210 self.assertEqual(set(s.namespaces.keys()), set(['', 'ex2', 'n']))
211
212 self.assertEqual('x', s.namespaces.get('UNKNOWN', 'x'))
213 self.assertEqual('example', s.namespaces.get('ex2', 'not used defa'))
214
216 "CSSStyleSheet.namespaces"
217
218
219 s = cssutils.css.CSSStyleSheet()
220 css = '@namespace n "new";'
221
222 s.insertRule(css + css)
223 self.assertEqual(css, s.cssText)
224 r = cssutils.css.CSSNamespaceRule(prefix='ex2', namespaceURI='example')
225 s.insertRule(r)
226 r = cssutils.css.CSSNamespaceRule(namespaceURI='default')
227 s.insertRule(r)
228
229 expcss = '''@namespace n "new";
230 @namespace ex2 "example";
231 @namespace "default";'''
232 self.assertEqual(s.cssText, expcss)
233 r.prefix = 'DEFAULT'
234 expcss = '''@namespace n "new";
235 @namespace ex2 "example";
236 @namespace DEFAULT "default";'''
237 self.assertEqual(s.cssText, expcss)
238
239
240 self.assertRaises(xml.dom.NamespaceErr, s.add, '@media all {x|a {left: 0}}')
241 mcss = '@media all {\n ex2|SEL1 {\n left: 0\n }\n }'
242 s.add(mcss)
243 expcss += '\n' + mcss
244 self.assertEqual(s.cssText, expcss)
245
246
247 self.assertRaises(xml.dom.NamespaceErr, s.add, 'x|a {top: 0}')
248 scss = 'n|SEL2 {\n top: 0\n }'
249 s.add(scss)
250 expcss += '\n' + scss
251 self.assertEqual(s.cssText, expcss)
252
253 mr = s.cssRules[3]
254 sr = s.cssRules[4]
255
256
257 self.assertRaises(xml.dom.NamespaceErr,
258 mr.cssRules[0]._setSelectorText, 'x|b')
259 oldsel, newsel = mr.cssRules[0].selectorText, 'n|SEL3, a'
260 mr.cssRules[0].selectorText = newsel
261 expcss = expcss.replace(oldsel, newsel)
262 self.assertEqual(s.cssText, expcss)
263
264 self.assertRaises(xml.dom.NamespaceErr,
265 sr._setSelectorText, 'x|b')
266 oldsel, newsel = sr.selectorText, 'ex2|SEL4, a'
267 sr.selectorText = newsel
268 expcss = expcss.replace(oldsel, newsel)
269 self.assertEqual(s.cssText, expcss)
270
271
272 self.assertRaises(xml.dom.NamespaceErr,
273 mr.cssRules[0].selectorList.append, 'x|b')
274 oldsel, newsel = mr.cssRules[0].selectorText, 'ex2|SELMR'
275 mr.cssRules[0].selectorList.append(newsel)
276 expcss = expcss.replace(oldsel, oldsel + ', ' + newsel)
277 self.assertEqual(s.cssText, expcss)
278
279 self.assertRaises(xml.dom.NamespaceErr,
280 sr.selectorList.append, 'x|b')
281 oldsel, newsel = sr.selectorText, 'ex2|SELSR'
282 sr.selectorList.append(newsel)
283 expcss = expcss.replace(oldsel, oldsel + ', ' + newsel)
284 self.assertEqual(s.cssText, expcss)
285
286 self.assertEqual(s.cssText, u'''@namespace n "new";
287 @namespace ex2 "example";
288 @namespace DEFAULT "default";
289 @media all {
290 n|SEL3, a, ex2|SELMR {
291 left: 0
292 }
293 }
294 ex2|SEL4, a, ex2|SELSR {
295 top: 0
296 }''')
297
299 "CSSStyleSheet.namespaces 3"
300
301 s = cssutils.css.CSSStyleSheet()
302 css = u'h|a { top: 0 }'
303 self.assertRaises(xml.dom.NamespaceErr, s.add, css)
304
305 s.add('@namespace x "html";')
306 self.assert_(s.namespaces['x'] == 'html')
307
308 r = cssutils.css.CSSStyleRule()
309 r.cssText = ((css, {'h': 'html'}))
310 s.add(r)
311 self.assertEqual(s.cssText, '@namespace x "html";\nx|a {\n top: 0\n }')
312
313
314 self.assertRaises(xml.dom.NamespaceErr, r.selectorList.append, 'h|b')
315 self.assertRaises(xml.dom.NamespaceErr, r.selectorList.append, 'y|b')
316 s.namespaces['y'] = 'html'
317 r.selectorList.append('y|b')
318 self.assertEqual(s.cssText,
319 u'@namespace y "html";\ny|a, y|b {\n top: 0\n }')
320
321 self.assertRaises(xml.dom.NoModificationAllowedErr,
322 s.namespaces.__delitem__, 'y')
323 self.assertEqual(s.cssText,
324 u'@namespace y "html";\ny|a, y|b {\n top: 0\n }')
325
326 s.cssRules[0].prefix = ''
327 self.assertEqual(s.cssText,
328 u'@namespace "html";\na, b {\n top: 0\n }')
329
330
331 s.cssRules[0].prefix = 'x'
332 s.cssRules[1].selectorText = 'a, b'
333 self.assertEqual(s.cssText,
334 u'@namespace x "html";\na, b {\n top: 0\n }')
335
336
362
364 "CSSStyleSheet.deleteRule()"
365 self.s.cssText = u'@charset "ascii"; @import "x"; @x; a {\n x: 1\n }@y;'
366 self.assertEqual(5, self.s.cssRules.length)
367
368 self.assertRaises(xml.dom.IndexSizeErr, self.s.deleteRule, 5)
369
370
371
372 r = self.s.cssRules[-1]
373 self.assertEqual(self.s, r.parentStyleSheet)
374 self.s.deleteRule(-1)
375 self.assertEqual(None, r.parentStyleSheet)
376
377 self.assertEqual(4, self.s.cssRules.length)
378 self.assertEqual(
379 u'@charset "ascii";\n@import "x";\n@x;\na {\n x: 1\n }', self.s.cssText)
380
381 self.s.deleteRule(0)
382 self.assertEqual(3, self.s.cssRules.length)
383 self.assertEqual(u'@import "x";\n@x;\na {\n x: 1\n }', self.s.cssText)
384
385 self.s.deleteRule(1)
386 self.assertEqual(2, self.s.cssRules.length)
387 self.assertEqual(u'@import "x";\na {\n x: 1\n }', self.s.cssText)
388
389 self.s.deleteRule(1)
390 self.assertEqual(1, self.s.cssRules.length)
391 self.assertEqual(u'@import "x";', self.s.cssText)
392
418
420 "CSSStyleSheet.add()"
421 full = cssutils.css.CSSStyleSheet()
422 sheet = cssutils.css.CSSStyleSheet()
423 css = ['@charset "ascii";',
424 '@import "x";',
425 '@namespace p "u";',
426 '@page {\n left: 0\n }',
427 '@font-face {\n color: red\n }',
428 '@media all {\n a {\n color: red\n }\n }',
429 'a {\n color: green\n }',
430 '/*comment*/',
431 '@x;'
432 ]
433 fullcss = u'\n'.join(css)
434 full.cssText = fullcss
435 self.assertEqual(full.cssText, fullcss)
436 for i, line in enumerate(css):
437
438 before = css[:i]
439 after = css[i+1:]
440 sheet.cssText = u''.join(before + after)
441 index = sheet.add(line)
442 if i < 3:
443 self.assertEqual(fullcss, sheet.cssText)
444 self.assertEqual(i, index)
445 else:
446 expected = before
447 expected.extend(after)
448 expected.append(line)
449 self.assertEqual(u'\n'.join(expected), sheet.cssText)
450 self.assertEqual(8, index)
451
452
453 if i == 1: line = '@import "x2";'
454 if i == 2: line = '@namespace p2 "u2";'
455 full.cssText = fullcss
456 index = full.add(line)
457 if i < 1:
458 self.assertEqual(fullcss, sheet.cssText)
459 self.assertEqual(i, index)
460 else:
461 expected = css[:i+1]
462 expected.append(line)
463 expected.extend(css[i+1:])
464 self.assertEqual(u'\n'.join(expected), full.cssText)
465 self.assertEqual(i+1, index)
466
468 "CSSStyleSheet.insertRule()"
469 s, L = self._gets()
470
471
472 self.assertRaises(xml.dom.IndexSizeErr,
473 s.insertRule, self.sr, -1)
474 self.assertRaises(xml.dom.IndexSizeErr,
475 s.insertRule, self.sr, s.cssRules.length + 1)
476
477 self.assertEqual(L, s.cssRules.length)
478
479
480 s.insertRule('a {}')
481 self.assertEqual(L+1, s.cssRules.length)
482
483 s.insertRule(self.sr)
484 self.assertEqual(L+2, s.cssRules.length)
485
486 s2, L2 = self._gets()
487 rulelist = s2.cssRules
488 del rulelist[:-2]
489 s.insertRule(rulelist)
490 self.assertEqual(L+2 + 2, s.cssRules.length)
491
492 - def _insertRule(self, rules, notbefore, notafter, anywhere,
493 checkdoubles=True):
494 """
495 helper
496 test if any rule in rules cannot be inserted before rules in before
497 or after rules in after but before and after rules in anywhere
498 """
499 for rule in rules:
500 for r in notbefore:
501 s = cssutils.css.CSSStyleSheet()
502 s.insertRule(r)
503 self.assertRaises(xml.dom.HierarchyRequestErr,
504 s.insertRule, rule, 0)
505 s = cssutils.css.CSSStyleSheet()
506 s.add(r)
507 self.assertRaises(xml.dom.HierarchyRequestErr,
508 s.insertRule, rule, 0)
509 for r in notafter:
510 s = cssutils.css.CSSStyleSheet()
511 s.insertRule(r)
512 self.assertRaises(xml.dom.HierarchyRequestErr,
513 s.insertRule, rule, 1)
514 s = cssutils.css.CSSStyleSheet()
515 s.add(r)
516 s.add(rule)
517
518 for r in anywhere:
519 s = cssutils.css.CSSStyleSheet()
520 s.insertRule(r)
521 s.insertRule(rule, 0)
522 s.insertRule(rule)
523 if checkdoubles:
524 self.assertEqual(s.cssRules.length, 3)
525 self.assertEqual(s, r.parentStyleSheet)
526
528 "CSSStyleSheet.insertRule(@charset)"
529 s, L = self._gets()
530 notbefore = (self.cr,)
531 notafter = (self.cr, self.ir, self.nr, self.mr, self.pr, self.sr,
532 self.c, self.ur)
533 anywhere = ()
534 self._insertRule((self.cr,),
535 notbefore, notafter, anywhere)
536
538 "CSSStyleSheet.insertRule(@import)"
539 s, L = self._gets()
540 notbefore = (self.cr,)
541 notafter = (self.nr, self.pr, self.mr, self.sr)
542 anywhere = (self.c, self.ur, self.ir)
543 self._insertRule((self.ir,),
544 notbefore, notafter, anywhere)
545
547 "CSSStyleSheet.insertRule(@namespace)"
548 s, L = self._gets()
549 notbefore = (self.cr, self.ir)
550 notafter = (self.pr, self.mr, self.sr)
551 anywhere = (self.c, self.ur, self.nr)
552 self._insertRule((self.nr,), notbefore, notafter, anywhere,
553 checkdoubles=False)
554
556 "CSSStyleSheet.insertRule(@media, @page, stylerule)"
557 s, L = self._gets()
558 notbefore = (self.cr, self.ir, self.nr)
559 notafter = ()
560 anywhere = (self.c, self.ur, self.mr, self.pr, self.sr)
561 self._insertRule((self.pr, self.mr, self.sr),
562 notbefore, notafter, anywhere)
563
573
575 "CSSStyleSheet.replaceUrls()"
576 cssutils.ser.prefs.keepAllProperties = True
577
578 css='''
579 @import "im1";
580 @import url(im2);
581 a {
582 background-image: url(c) !important;
583 background-\image: url(b);
584 background: url(a) no-repeat !important;
585 }'''
586 s = cssutils.parseString(css)
587 s.replaceUrls(lambda old: "NEW" + old)
588 self.assertEqual(u'@import "NEWim1";', s.cssRules[0].cssText)
589 self.assertEqual(u'NEWim2', s.cssRules[1].href)
590 self.assertEqual(u'''background-image: url(NEWc) !important;
591 background-\\image: url(NEWb);
592 background: url(NEWa) no-repeat !important''', s.cssRules[2].style.cssText)
593
594 cssutils.ser.prefs.keepAllProperties = False
595
613
615 "CSSStyleRule (incomplete)"
616 tests = {
617 u'@import "a': u'@import "a";',
618 u'a { x: 1': u'a {\n x: 1\n }',
619 u'a { font-family: "arial sans':
620 u'a {\n font-family: "arial sans"\n }',
621 }
622 self.do_equal_p(tests)
623
625 "CSSStyleSheet NoModificationAllowedErr"
626 css = cssutils.css.CSSStyleSheet(readonly=True)
627
628 self.assertEqual(True, css._readonly)
629
630 self.assertRaises(xml.dom.NoModificationAllowedErr,
631 css._setCssText, u'@x;')
632 self.assertRaises(xml.dom.NoModificationAllowedErr,
633 css.insertRule, self.rule)
634 self.assertRaises(xml.dom.NoModificationAllowedErr,
635 css.insertRule, self.rule, 0)
636 self.assertRaises(xml.dom.NoModificationAllowedErr,
637 css.deleteRule, 0)
638
640 "CSSStyleSheet.__repr__(), .__str__()"
641 href = 'file:foo.css'
642 title = 'title-of-css'
643
644 s = cssutils.css.CSSStyleSheet(href=href, title=title)
645
646 self.assert_(href in str(s))
647 self.assert_(title in str(s))
648
649 s2 = eval(repr(s))
650 self.assert_(isinstance(s2, s.__class__))
651 self.assert_(href == s2.href)
652 self.assert_(title == s2.title)
653
654
655 if __name__ == '__main__':
656 import unittest
657 unittest.main()
658