root/trunk/test/w3c/testCSS.py

Revision 402, 36.1 kB (checked in by sholloway, 5 years ago)

Fix for ticket:50 to handle section 4.2 of the CSS 2.1 spec. Conformant will all recoverable errors.

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ Copyright (C) 2002-2004  TechGame Networks, LLC.
4 ##~
5 ##~ This library is free software; you can redistribute it and/or
6 ##~ modify it under the terms of the BSD style License as found in the
7 ##~ LICENSE file included with this distribution.
8 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
10 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #~ Imports
12 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13
14 import unittest
15 import sys
16
17 from TG.w3c import css
18
19 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 #~ Definitions
21 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22
23 class TestCSSInlineAttribute(unittest.TestCase):
24     def setUp(self):
25         self.parser = css.CSSParser()
26
27     def assertCSSAttrValueEqual(self, good, equalfn=None, **kwAttributes):
28         if equalfn is None:
29             equalfn = self.assertEqual
30         fn = lambda r, v: equalfn(r['value'], v)
31         self.assertCSSAttrEqual(good, fn, **kwAttributes)
32
33     def assertCSSAttrEqual(self, good, equalfn=None, **kwAttributes):
34         if equalfn is None:
35             equalfn = self.assertEqual
36         result = self.parser.parseAttributes(kwAttributes)
37         equalfn(result, good)
38
39     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40     #~ Tests
41     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42
43     def testOneValue(self):
44         result = {'one':'1'}
45         self.assertCSSAttrEqual(result, one='1')
46
47     def testMultipleValue(self):
48         result = {'one':'1', 'two':'2', 'three':'3'}
49         self.assertCSSAttrEqual(result, one='1', two='2', three='3')
50
51     def testListValue(self):
52         result = ['1','2','3','4','5']
53         self.assertCSSAttrValueEqual(result, value='1, 2, 3, 4, 5,')
54
55     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56
57     def testIdent(self):
58         self.assertCSSAttrValueEqual('anIdent', value='anIdent')
59         self.assertCSSAttrValueEqual('anIdent-with-dashes', value='anIdent-with-dashes')
60
61     def testNumber(self):
62         self.assertCSSAttrValueEqual('1', value='1')
63         self.assertCSSAttrValueEqual('2.78', value='2.78')
64         self.assertCSSAttrValueEqual(('1', 'em'), value='1em')
65         self.assertCSSAttrValueEqual(('2.78', 'pt'), value='2.78pt')
66         self.assertCSSAttrValueEqual(('1', '%'), value='1%')
67         self.assertCSSAttrValueEqual(('2.78', '%'), value='2.78%')
68
69     def testRGB(self):
70         self.assertCSSAttrValueEqual('#ffee00', value='#ffee00')
71         self.assertCSSAttrValueEqual('#fe0', value='#fe0')
72
73     def testURLs(self):
74         result = 'http://stuff.com/more'
75         self.assertCSSAttrValueEqual(result, value='url(\'%s\')'%result)
76         self.assertCSSAttrValueEqual(result, value='url(\"%s\")'%result)
77         self.assertCSSAttrValueEqual(result, value='url(%s)'%result)
78
79         self.assertCSSAttrValueEqual(result, value='url( \'%s\')'%result)
80         self.assertCSSAttrValueEqual(result, value='url( \"%s\")'%result)
81         self.assertCSSAttrValueEqual(result, value='url( %s)'%result)
82         self.assertCSSAttrValueEqual(result, value='url(\'%s\' )'%result)
83         self.assertCSSAttrValueEqual(result, value='url(\"%s\" )'%result)
84         self.assertCSSAttrValueEqual(result, value='url(%s )'%result)
85         self.assertCSSAttrValueEqual(result, value='url( \'%s\' )'%result)
86         self.assertCSSAttrValueEqual(result, value='url( \"%s\" )'%result)
87         self.assertCSSAttrValueEqual(result, value='url( %s )'%result)
88    
89
90     def testFunction(self):
91         def assertEqualFn(result, (name, params)):
92             self.assertEqual(result.name, name)
93             self.assertEqual(result.params, params)
94
95         self.assertCSSAttrValueEqual(('testFn', ['aParam']), equalfn=assertEqualFn,
96                 value='testFn(aParam)')
97         self.assertCSSAttrValueEqual(('testFn', ['aParam1', 'aParam2']), assertEqualFn,
98                 value='testFn(aParam1, aParam2)')
99         self.assertCSSAttrValueEqual(('testFn', ['aParam1', 'aParam2']), assertEqualFn,
100                 value='testFn(aParam1 aParam2)')
101         self.assertCSSAttrValueEqual(
102                 ('testFn', ['aParam', '1', '1.2', ('10', '%'), ('10.5', '%'), "aString", 'another', '#c0ffee', 'http://stuff.com/more']),
103                 equalfn=assertEqualFn,
104                 value='testFn(aParam, 1, 1.2, 10%, 10.5%, "aString", \'another\', #c0ffee, url(http://stuff.com/more))')
105
106     def testIdentList(self):
107         result = 'anIdent anIdent-with-dashes _anUnderScore'.split()
108         self.assertCSSAttrValueEqual(result, value='anIdent anIdent-with-dashes _anUnderScore')
109         self.assertCSSAttrValueEqual(result, value='anIdent, anIdent-with-dashes, _anUnderScore')
110
111         self.assertCSSAttrValueEqual(result, value='anIdent anIdent-with-dashes, _anUnderScore,')
112         self.assertCSSAttrValueEqual(result, value='anIdent, anIdent-with-dashes, _anUnderScore,')
113
114     def testMixedList(self):
115         result = ['aParam', '1', '1.2', ('10', '%'), ('10.5', '%'), "aString", 'another', '#c0ffee', 'http://stuff.com/more']
116         self.assertCSSAttrValueEqual(result, value='aParam, 1, 1.2, 10%, 10.5%, "aString", \'another\', #c0ffee, url(http://stuff.com/more)')
117
118 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
119
120 class TestCSSInline(unittest.TestCase):
121     def setUp(self):
122         self.parser = css.CSSParser()
123
124     def assertCSSValueEqual(self, testcss, good, equalfn=None):
125         if equalfn is None: equalfn = self.assertEqual
126         fn = lambda r, v: equalfn(r['value'], v)
127         self.assertCSSEqual(testcss, good, fn)
128
129     def assertCSSEqual(self, testcss, good, equalfn=None):
130         if equalfn is None:
131             equalfn = self.assertEqual
132         result = self.parser.parseInline(testcss)
133         equalfn(result, good)
134         result = self.parser.parseInline('{'+testcss+'}')
135         equalfn(result, good)
136
137     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
138     #~ Tests
139     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140
141     def testOneValue(self):
142         result = {'one':'1'}
143         self.assertCSSEqual('one: 1', result)
144         self.assertCSSEqual('one:1', result)
145         self.assertCSSEqual('one 1', {})
146
147     def testMultipleValue(self):
148         result = {'one':'1', 'two':'2', 'three':'3'}
149         self.assertCSSEqual('one: 1;two: 2;three: 3', result)
150         self.assertCSSEqual('one:1;two:2;three:3', result)
151         self.assertCSSEqual('one 1;two 2;three 3', {})
152
153     def testListValue(self):
154         result = ['1','2','3','4','5']
155         self.assertCSSValueEqual('value: 1, 2, 3, 4, 5,', result)
156         self.assertCSSValueEqual('value: 1, 2, 3, 4, 5,', result)
157         self.assertCSSValueEqual('value: 1 2 3 4 5', result)
158         self.assertCSSValueEqual('value: 1 2 3, 4 5,', result)
159
160     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161
162     def testIdent(self):
163         self.assertCSSValueEqual('value: anIdent', 'anIdent')
164         self.assertCSSValueEqual('value: anIdent-with-dashes', 'anIdent-with-dashes')
165
166     def testNumber(self):
167         self.assertCSSValueEqual('value: 1', '1')
168         self.assertCSSValueEqual('value: 2.78', '2.78')
169         self.assertCSSValueEqual('value: 1em', ('1', 'em'))
170         self.assertCSSValueEqual('value: 2.78pt', ('2.78', 'pt'))
171         self.assertCSSValueEqual('value: 1%', ('1', '%'))
172         self.assertCSSValueEqual('value: 2.78%', ('2.78', '%'))
173
174     def testString(self):
175         result = 'a test string'
176         self.assertCSSValueEqual('value: \'%s\''%result, result)
177         self.assertCSSValueEqual('value: \"%s\"'%result, result)
178
179     def testRGB(self):
180         self.assertCSSValueEqual('value: #ffee00', '#ffee00')
181         self.assertCSSValueEqual('value: #fe0', '#fe0')
182
183     def testURLs(self):
184         result = 'http://stuff.com/more'
185         self.assertCSSValueEqual('value: url(\'%s\')'%result, result)
186         self.assertCSSValueEqual('value: url(\"%s\")'%result, result)
187         self.assertCSSValueEqual('value: url(%s)'%result, result)
188
189     def testFunction(self):
190         def assertEqualFn(result, (name, params)):
191             self.assertEqual(result.name, name)
192             self.assertEqual(result.params, params)
193
194         self.assertCSSValueEqual('value: testFn(aParam)', ('testFn', ['aParam']), assertEqualFn)
195         self.assertCSSValueEqual('value: testFn(aParam1, aParam2)', ('testFn', ['aParam1', 'aParam2']), assertEqualFn)
196         self.assertCSSValueEqual('value: testFn(aParam1 aParam2)', ('testFn', ['aParam1', 'aParam2']), assertEqualFn)
197         self.assertCSSValueEqual('value: testFn(aParam, 1, 1.2, 10%, 10.5%, "aString", \'another\', #c0ffee, url(http://stuff.com/more))',
198                 ('testFn', ['aParam', '1', '1.2', ('10', '%'), ('10.5', '%'), "aString", 'another', '#c0ffee', 'http://stuff.com/more']), assertEqualFn)
199
200     def testIdentList(self):
201         result = 'anIdent anIdent-with-dashes _anUnderScore'.split()
202         self.assertCSSValueEqual('value: anIdent anIdent-with-dashes _anUnderScore', result)
203         self.assertCSSValueEqual('value: anIdent, anIdent-with-dashes, _anUnderScore', result)
204
205         self.assertCSSValueEqual('value: anIdent anIdent-with-dashes, _anUnderScore,', result)
206         self.assertCSSValueEqual('value: anIdent, anIdent-with-dashes, _anUnderScore,', result)
207
208     def testMixedList(self):
209         result = ['aParam', '1', '1.2', ('10', '%'), ('10.5', '%'), "aString", 'another', '#c0ffee', 'http://stuff.com/more']
210         self.assertCSSValueEqual('value: aParam, 1, 1.2, 10%, 10.5%, "aString", \'another\', #c0ffee, url(http://stuff.com/more)', result)
211
212 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213
214 class TestCSSSelectors(unittest.TestCase):
215     def setUp(self):
216         self.parser = css.CSSParser()
217     def tearDown(self):
218         del self.parser
219
220     def parseCSS(self, testcss):
221         return self.parser.parse(testcss)
222
223     def assertSpecifityEqual(self, testcss, goodValue):
224         stylesheet = self.parseCSS(testcss)
225         for selector in stylesheet.iterkeys():
226             self.assertEqual(selector.specificity(), goodValue)
227
228     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229
230     def testSimplest(self):
231         stylesheet = self.parseCSS('node{value: 1}')
232         self.assertEqual(len(stylesheet), 1)
233
234         (selector, declarations), = stylesheet.items()
235         self.assertEqual(selector.name, 'node')
236         self.assertEqual(selector.qualifiers, ())
237         self.assertEqual(declarations, {'value':'1'})
238
239     def testMultiple(self):
240         stylesheet = self.parseCSS('nodeA, nodeB, nodeC {value: 1}')
241         for selector, declarations in stylesheet.items():
242             self.assertEqual(declarations , {'value':'1'})
243             self.assert_(selector.name in ('nodeA', 'nodeB', 'nodeC'))
244             self.assertEqual(selector.qualifiers, ())
245
246     def testCommentInString(self):
247         stylesheet = self.parseCSS('node{start: "stuff /* here"; stop: "more */ stuff"; /* not-included: True */}')
248         self.assertEqual(len(stylesheet), 1)
249
250         (selector, declarations), = stylesheet.items()
251         self.assertEqual(selector.name, 'node')
252         self.assertEqual(selector.qualifiers, ())
253         self.assertEqual(len(declarations), 2)
254         self.assertEqual(declarations, {'start':'stuff /* here', 'stop':'more */ stuff'})
255
256     def testMultipleWithNewlines(self):
257         stylesheet = self.parseCSS('nodeA,\nnodeB,\nnodeC\n{value: 1}')
258         for selector, declarations in stylesheet.items():
259             self.assertEqual(declarations , {'value':'1'})
260             self.assert_(selector.name in ('nodeA', 'nodeB', 'nodeC'))
261             self.assertEqual(selector.qualifiers, ())
262
263     def testMultipleBlocks(self):
264         stylesheet = self.parseCSS('nodeA{value: 1}nodeB.myClass{stuff: 2}nodeC#myId{grok:"yes"}')
265         for selector, declarations in stylesheet.items():
266             if selector.name == 'nodeA':
267                 self.assertEqual(declarations, {'value':'1'})
268                 self.assertEqual(selector.qualifiers, ())
269             elif selector.name == 'nodeB':
270                 self.assertEqual(declarations, {'stuff':'2'})
271                 self.assertEqual(selector.qualifiers[0].classId, 'myClass')
272             elif selector.name == 'nodeC':
273                 self.assertEqual(declarations, {'grok':'yes'})
274                 self.assertEqual(selector.qualifiers[0].hashId, 'myId')
275             else:
276                 self.fail('Expected a selector name of "nodeA", "nodeB", or "nodeC", but found' + selector.name)
277
278     def testId(self):
279         stylesheet = self.parseCSS('node#myId{value: 1}')
280         for selector, declarations in stylesheet.items():
281             self.assertEqual(declarations, {'value':'1'})
282             self.assertEqual(selector.name, 'node')
283             self.assertEqual(selector.qualifiers[0].hashId, 'myId')
284
285     def testClass(self):
286         stylesheet = self.parseCSS('node.myClass{value: 1}')
287         for selector, declarations in stylesheet.items():
288             self.assertEqual(declarations, {'value':'1'})
289             self.assertEqual(selector.name, 'node')
290             self.assertEqual(selector.qualifiers[0].classId, 'myClass')
291
292     def testClassId(self):
293         stylesheet = self.parseCSS('node.myClass#myId{value: 1}')
294         for selector, declarations in stylesheet.items():
295             self.assertEqual(declarations, {'value':'1'})
296             self.assertEqual(selector.name, 'node')
297             self.assertEqual(selector.qualifiers[0].classId, 'myClass')
298             self.assertEqual(selector.qualifiers[1].hashId, 'myId')
299
300     def testIdClass(self):
301         stylesheet = self.parseCSS('node#myId.myClass{value: 1}')
302         for selector, declarations in stylesheet.items():
303             self.assertEqual(declarations, {'value':'1'})
304             self.assertEqual(selector.name, 'node')
305             self.assertEqual(selector.qualifiers[0].hashId, 'myId')
306             self.assertEqual(selector.qualifiers[1].classId, 'myClass')
307
308     def testAttributeExists(self):
309         stylesheet = self.parseCSS('node[myAttr]{value: 1}')
310         for selector, declarations in stylesheet.items():
311             self.assertEqual(declarations, {'value':'1'})
312             self.assertEqual(selector.name, 'node')
313             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
314             self.assertEqual(selector.qualifiers[0].op, None)
315             self.assertEqual(selector.qualifiers[0].value, NotImplemented)
316
317     def testAttributeEqual(self):
318         stylesheet = self.parseCSS('node[myAttr=something]{value: 1}')
319         for selector, declarations in stylesheet.items():
320             self.assertEqual(declarations, {'value':'1'})
321             self.assertEqual(selector.name, 'node')
322             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
323             self.assertEqual(selector.qualifiers[0].op, '=')
324             self.assertEqual(selector.qualifiers[0].value, 'something')
325
326     def testAttributeContains(self):
327         stylesheet = self.parseCSS('node[myAttr~=something]{value: 1}')
328         for selector, declarations in stylesheet.items():
329             self.assertEqual(declarations, {'value':'1'})
330             self.assertEqual(selector.name, 'node')
331             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
332             self.assertEqual(selector.qualifiers[0].op, '~=')
333             self.assertEqual(selector.qualifiers[0].value, 'something')
334
335     def testAttributeContains2(self):
336         stylesheet = self.parseCSS('node[myAttr|=something]{value: 1}')
337         for selector, declarations in stylesheet.items():
338             self.assertEqual(declarations, {'value':'1'})
339             self.assertEqual(selector.name, 'node')
340             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
341             self.assertEqual(selector.qualifiers[0].op, '|=')
342             self.assertEqual(selector.qualifiers[0].value, 'something')
343
344     def testPseudo(self):
345         stylesheet = self.parseCSS('node:myPseudo{value: 1}')
346         for selector, declarations in stylesheet.items():
347             self.assertEqual(declarations, {'value':'1'})
348             self.assertEqual(selector.name, 'node')
349             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
350             self.assertEqual(selector.qualifiers[0].params, ())
351
352     def testPseudoFn(self):
353         stylesheet = self.parseCSS('node:myPseudo(paramA){value: 1}')
354         for selector, declarations in stylesheet.items():
355             self.assertEqual(declarations, {'value':'1'})
356             self.assertEqual(selector.name, 'node')
357             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
358             self.assertEqual(selector.qualifiers[0].params, ('paramA',))
359
360         stylesheet = self.parseCSS('node:myPseudo(paramA, paramB){value: 1}')
361         for selector, declarations in stylesheet.items():
362             self.assertEqual(declarations, {'value':'1'})
363             self.assertEqual(selector.name, 'node')
364             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
365             self.assertEqual(selector.qualifiers[0].params, ('paramA', 'paramB'))
366
367         stylesheet = self.parseCSS('node:myPseudo(paramA paramB){value: 1}')
368         for selector, declarations in stylesheet.items():
369             self.assertEqual(declarations, {'value':'1'})
370             self.assertEqual(selector.name, 'node')
371             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
372             self.assertEqual(selector.qualifiers[0].params, ('paramA', 'paramB'))
373
374     def testCombinerPlain(self):
375         stylesheet = self.parseCSS('nodeA nodeB {value: 1}')
376         for selector, declarations in stylesheet.items():
377             self.assertEqual(declarations, {'value':'1'})
378             self.assertEqual(selector.name, 'nodeB')
379             self.assertEqual(selector.qualifiers[0].op, ' ')
380             self.assertEqual(selector.qualifiers[0].selector.name, 'nodeA')
381             self.assertEqual(selector.qualifiers[0].selector.qualifiers, ())
382
383     def testCombinerAdd(self):
384         stylesheet = self.parseCSS('nodeA + nodeB {value: 1}')
385         for selector, declarations in stylesheet.items():
386             self.assertEqual(declarations, {'value':'1'})
387             self.assertEqual(selector.name, 'nodeB')
388             self.assertEqual(selector.qualifiers[0].op, '+')
389             self.assertEqual(selector.qualifiers[0].selector.name, 'nodeA')
390             self.assertEqual(selector.qualifiers[0].selector.qualifiers, ())
391
392     def testCombinerGreater(self):
393         stylesheet = self.parseCSS('nodeA > nodeB {value: 1}')
394         for selector, declarations in stylesheet.items():
395             self.assertEqual(declarations, {'value':'1'})
396             self.assertEqual(selector.name, 'nodeB')
397             self.assertEqual(selector.qualifiers[0].op, '>')
398             self.assertEqual(selector.qualifiers[0].selector.name, 'nodeA')
399             self.assertEqual(selector.qualifiers[0].selector.qualifiers, ())
400
401     def testSpecifity(self):
402         self.assertSpecifityEqual('*             {}', (0,0,0,0))
403         self.assertSpecifityEqual('li            {}', (0,0,0,1))
404         self.assertSpecifityEqual('li:first-line {}', (0,0,0,2))
405         self.assertSpecifityEqual('ul li         {}', (0,0,0,2))
406         self.assertSpecifityEqual('ul ol+li      {}', (0,0,0,3))
407         self.assertSpecifityEqual('h1 + *[rel=up]{}', (0,0,1,1))
408         self.assertSpecifityEqual('ul ol li.red  {}', (0,0,1,3))
409         self.assertSpecifityEqual('li.red.level  {}', (0,0,2,1))
410         self.assertSpecifityEqual('#x34y         {}', (0,1,0,0))
411
412     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
413
414     def testAnyId(self):
415         stylesheet = self.parseCSS('*#myId{value: 1}')
416         for selector, declarations in stylesheet.items():
417             self.assertEqual(declarations, {'value':'1'})
418             self.assertEqual(selector.name, '*')
419             self.assertEqual(selector.qualifiers[0].hashId, 'myId')
420
421         stylesheet = self.parseCSS('#myId{value: 1}')
422         for selector, declarations in stylesheet.items():
423             self.assertEqual(declarations, {'value':'1'})
424             self.assertEqual(selector.name, '*')
425             self.assertEqual(selector.qualifiers[0].hashId, 'myId')
426
427     def testAnyClass(self):
428         stylesheet = self.parseCSS('*.myClass{value: 1}')
429         for selector, declarations in stylesheet.items():
430             self.assertEqual(declarations, {'value':'1'})
431             self.assertEqual(selector.name, '*')
432             self.assertEqual(selector.qualifiers[0].classId, 'myClass')
433
434         stylesheet = self.parseCSS('.myClass{value: 1}')
435         for selector, declarations in stylesheet.items():
436             self.assertEqual(declarations, {'value':'1'})
437             self.assertEqual(selector.name, '*')
438             self.assertEqual(selector.qualifiers[0].classId, 'myClass')
439
440     def testAnyClassId(self):
441         stylesheet = self.parseCSS('*.myClass#myId{value: 1}')
442         for selector, declarations in stylesheet.items():
443             self.assertEqual(declarations, {'value':'1'})
444             self.assertEqual(selector.name, '*')
445             self.assertEqual(selector.qualifiers[0].classId, 'myClass')
446             self.assertEqual(selector.qualifiers[1].hashId, 'myId')
447
448         stylesheet = self.parseCSS('.myClass#myId{value: 1}')
449         for selector, declarations in stylesheet.items():
450             self.assertEqual(declarations, {'value':'1'})
451             self.assertEqual(selector.name, '*')
452             self.assertEqual(selector.qualifiers[0].classId, 'myClass')
453             self.assertEqual(selector.qualifiers[1].hashId, 'myId')
454
455     def testAnyIdClass(self):
456         stylesheet = self.parseCSS('*#myId.myClass{value: 1}')
457         for selector, declarations in stylesheet.items():
458             self.assertEqual(declarations, {'value':'1'})
459             self.assertEqual(selector.name, '*')
460             self.assertEqual(selector.qualifiers[0].hashId, 'myId')
461             self.assertEqual(selector.qualifiers[1].classId, 'myClass')
462
463         stylesheet = self.parseCSS('#myId.myClass{value: 1}')
464         for selector, declarations in stylesheet.items():
465             self.assertEqual(declarations, {'value':'1'})
466             self.assertEqual(selector.name, '*')
467             self.assertEqual(selector.qualifiers[0].hashId, 'myId')
468             self.assertEqual(selector.qualifiers[1].classId, 'myClass')
469
470     def testAnyAttributeExists(self):
471         stylesheet = self.parseCSS('*[myAttr]{value: 1}')
472         for selector, declarations in stylesheet.items():
473             self.assertEqual(declarations, {'value':'1'})
474             self.assertEqual(selector.name, '*')
475             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
476             self.assertEqual(selector.qualifiers[0].op, None)
477             self.assertEqual(selector.qualifiers[0].value, NotImplemented)
478
479         stylesheet = self.parseCSS('[myAttr]{value: 1}')
480         for selector, declarations in stylesheet.items():
481             self.assertEqual(declarations, {'value':'1'})
482             self.assertEqual(selector.name, '*')
483             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
484             self.assertEqual(selector.qualifiers[0].op, None)
485             self.assertEqual(selector.qualifiers[0].value, NotImplemented)
486
487     def testAnyAttributeEqual(self):
488         stylesheet = self.parseCSS('*[myAttr=something]{value: 1}')
489         for selector, declarations in stylesheet.items():
490             self.assertEqual(declarations, {'value':'1'})
491             self.assertEqual(selector.name, '*')
492             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
493             self.assertEqual(selector.qualifiers[0].op, '=')
494             self.assertEqual(selector.qualifiers[0].value, 'something')
495
496         stylesheet = self.parseCSS('[myAttr=something]{value: 1}')
497         for selector, declarations in stylesheet.items():
498             self.assertEqual(declarations, {'value':'1'})
499             self.assertEqual(selector.name, '*')
500             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
501             self.assertEqual(selector.qualifiers[0].op, '=')
502             self.assertEqual(selector.qualifiers[0].value, 'something')
503
504     def testAnyAttributeContains(self):
505         stylesheet = self.parseCSS('*[myAttr~=something]{value: 1}')
506         for selector, declarations in stylesheet.items():
507             self.assertEqual(declarations, {'value':'1'})
508             self.assertEqual(selector.name, '*')
509             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
510             self.assertEqual(selector.qualifiers[0].op, '~=')
511             self.assertEqual(selector.qualifiers[0].value, 'something')
512
513         stylesheet = self.parseCSS('[myAttr~=something]{value: 1}')
514         for selector, declarations in stylesheet.items():
515             self.assertEqual(declarations, {'value':'1'})
516             self.assertEqual(selector.name, '*')
517             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
518             self.assertEqual(selector.qualifiers[0].op, '~=')
519             self.assertEqual(selector.qualifiers[0].value, 'something')
520
521     def testAnyAttributeContains2(self):
522         stylesheet = self.parseCSS('*[myAttr|=something]{value: 1}')
523         for selector, declarations in stylesheet.items():
524             self.assertEqual(declarations, {'value':'1'})
525             self.assertEqual(selector.name, '*')
526             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
527             self.assertEqual(selector.qualifiers[0].op, '|=')
528             self.assertEqual(selector.qualifiers[0].value, 'something')
529
530         stylesheet = self.parseCSS('[myAttr|=something]{value: 1}')
531         for selector, declarations in stylesheet.items():
532             self.assertEqual(declarations, {'value':'1'})
533             self.assertEqual(selector.name, '*')
534             self.assertEqual(selector.qualifiers[0].name, 'myAttr')
535             self.assertEqual(selector.qualifiers[0].op, '|=')
536             self.assertEqual(selector.qualifiers[0].value, 'something')
537
538     def testAnyPseudo(self):
539         stylesheet = self.parseCSS('*:myPseudo{value: 1}')
540         for selector, declarations in stylesheet.items():
541             self.assertEqual(declarations, {'value':'1'})
542             self.assertEqual(selector.name, '*')
543             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
544             self.assertEqual(selector.qualifiers[0].params, ())
545
546         stylesheet = self.parseCSS(':myPseudo{value: 1}')
547         for selector, declarations in stylesheet.items():
548             self.assertEqual(declarations, {'value':'1'})
549             self.assertEqual(selector.name, '*')
550             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
551             self.assertEqual(selector.qualifiers[0].params, ())
552
553     def testAnyPseudoFn(self):
554         stylesheet = self.parseCSS('*:myPseudo(paramA){value: 1}')
555         for selector, declarations in stylesheet.items():
556             self.assertEqual(declarations, {'value':'1'})
557             self.assertEqual(selector.name, '*')
558             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
559             self.assertEqual(selector.qualifiers[0].params, ('paramA',))
560
561         stylesheet = self.parseCSS(':myPseudo(paramA){value: 1}')
562         for selector, declarations in stylesheet.items():
563             self.assertEqual(declarations, {'value':'1'})
564             self.assertEqual(selector.name, '*')
565             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
566             self.assertEqual(selector.qualifiers[0].params, ('paramA',))
567
568         #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
569
570         stylesheet = self.parseCSS('*:myPseudo(paramA, paramB){value: 1}')
571         for selector, declarations in stylesheet.items():
572             self.assertEqual(declarations, {'value':'1'})
573             self.assertEqual(selector.name, '*')
574             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
575             self.assertEqual(selector.qualifiers[0].params, ('paramA', 'paramB'))
576
577         stylesheet = self.parseCSS(':myPseudo(paramA, paramB){value: 1}')
578         for selector, declarations in stylesheet.items():
579             self.assertEqual(declarations, {'value':'1'})
580             self.assertEqual(selector.name, '*')
581             self.assertEqual(selector.qualifiers[0].name, 'myPseudo')
582             self.assertEqual(selector.qualifiers[0].params, ('paramA', 'paramB'))
583
584     def testAnyCombinerPlain(self):
585         stylesheet = self.parseCSS('* nodeB {value: 1}')
586         for selector, declarations in stylesheet.items():
587             self.assertEqual(declarations, {'value':'1'})
588             self.assertEqual(selector.name, 'nodeB')
589             self.assertEqual(selector.qualifiers[0].op, ' ')
590             self.assertEqual(selector.qualifiers[0].selector.name, '*')
591             self.assertEqual(selector.qualifiers[0].selector.qualifiers, ())
592
593     def testAnyCombinerAdd(self):
594         stylesheet = self.parseCSS('* + nodeB {value: 1}')
595         for selector, declarations in stylesheet.items():
596             self.assertEqual(declarations, {'value':'1'})
597             self.assertEqual(selector.name, 'nodeB')
598             self.assertEqual(selector.qualifiers[0].op, '+')
599             self.assertEqual(selector.qualifiers[0].selector.name, '*')
600             self.assertEqual(selector.qualifiers[0].selector.qualifiers, ())
601
602     def testAnyCombinerGreater(self):
603         stylesheet = self.parseCSS('* > nodeB {value: 1}')
604         for selector, declarations in stylesheet.items():
605             self.assertEqual(declarations, {'value':'1'})
606             self.assertEqual(selector.name, 'nodeB')
607             self.assertEqual(selector.qualifiers[0].op, '>')
608             self.assertEqual(selector.qualifiers[0].selector.name, '*')
609             self.assertEqual(selector.qualifiers[0].selector.qualifiers, ())
610
611
612 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
613
614 class TestCSSAtRules(unittest.TestCase):
615     def setUp(self):
616         self.builder = css.CSSBuilder()
617         self.builder.atImport = self._atImport
618         self.builder.atMedia = self._atMedia
619         self.builder.atPage = self._atPage
620         self.builder.atPageMargin = self._atPageMargin
621         self.builder.atFontFace = self._atFontFace
622         self.parser = css.CSSParser(self.builder)
623
624         self.cssImportString = None
625         self.goodImportValue = None
626         self.goodMediumValue = None
627
628     def tearDown(self):
629         del self.parser
630
631     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
632
633     def _atMedia(self, mediums, ruleset):
634         self.assertEqual(mediums, self.goodMediumValue)
635         return ruleset
636
637     def _atImport(self, import_, mediums, cssParser):
638         self.assert_(self.parser is cssParser)
639         self.assertEqual(import_, self.goodImportValue)
640         self.assertEqual(mediums, self.goodMediumValue)
641         if self.cssImportString is not None:
642             return cssParser.parse(self.cssImportString)
643         else: return None
644
645     def _atPage(self, page, pseudoPage, properties, margins):
646         self._atPageArgs = page, pseudoPage, dict([(n,v) for n,v,i in properties]), margins
647         return [dict([(n,v) for n,v,i in properties])]
648
649     def _atPageMargin(self, page, pseudoPage, marginName, properties):
650         return (marginName, dict([(n,v) for n,v,i in properties]))
651
652     def _atFontFace(self, declarations):
653         self._atFontFaceArgs = dict([(n,v) for n,v,i in declarations])
654         return [self._atFontFaceArgs]
655
656     def _atIdent(self, atIdent, cssParser, src):
657         self._atIdentCalled = atIdent
658         return src, None
659
660     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
661
662     def _checkResultStylesheet(self, stylesheet):
663         for selector, declarations in stylesheet.items():
664             self.assertEqual(declarations, {'value':'1'})
665             self.assertEqual(selector.name, 'node')
666             self.assertEqual(selector.qualifiers, ())
667
668     def parseCSS(self, testcss):
669         return self.parser.parse(testcss)
670
671     def testAtImport(self):
672         self.cssImportString = 'node{value: 1}'
673         self.goodImportValue = 'stuff'
674         self.goodMediumValue = []
675         stylesheet = self.parseCSS('@import "%s";'%self.goodImportValue)
676         self._checkResultStylesheet(stylesheet)
677         stylesheet = self.parseCSS('@import \'%s\';'%self.goodImportValue)
678         self._checkResultStylesheet(stylesheet)
679
680     def testAtImportWithMediums(self):
681         self.cssImportString = 'node{value: 1}'
682         self.goodImportValue = 'otherStuff'
683         self.goodMediumValue = ['paper', 'towel']
684         stylesheet = self.parseCSS('@import url("%s") paper, towel;'%self.goodImportValue)
685         self._checkResultStylesheet(stylesheet)
686         stylesheet = self.parseCSS('@import url(%s) paper, towel;'%self.goodImportValue)
687         self._checkResultStylesheet(stylesheet)
688
689     def testAtNamespace(self):
690         testcss = """
691         @namespace "default:namespace";
692         @namespace foo "foo:namespace";
693
694         |node{color: black}
695         |*{color: black}
696
697         *|node{color: black}
698         *|*{color: black}
699
700         foo|node{color: black}
701         foo|*{color: black}
702         """
703         stylesheet = self.parseCSS(testcss)
704
705         for selector, declarations in stylesheet.items():
706             self.assertEqual(declarations,{'color': 'black'})
707
708             if selector.nsPrefix == '':
709                 self.assert_(selector.name in ('*', 'node'))
710                 self.assertEqual(selector.namespace, None)
711             elif selector.nsPrefix == '*':
712                 self.assert_(selector.name in ('*', 'node'))
713                 self.assertEqual(selector.namespace, "*")
714             elif selector.nsPrefix == 'foo':
715                 self.assert_(selector.name in ('*', 'node'))
716                 self.assertEqual(selector.namespace, "foo:namespace")
717             else:
718                 self.fail('Invalid state for selector %r'%selector)
719
720     def testAtMedia(self):
721         self.goodMediumValue = ['paper']
722         stylesheet = self.parseCSS('@media paper {node{value: 1}}')
723         self._checkResultStylesheet(stylesheet)
724
725         self.goodMediumValue = ['paper', 'towel']
726         stylesheet = self.parseCSS('@media paper, towel {node{value: 1}}')
727         self._checkResultStylesheet(stylesheet)
728
729     def testAtPage(self):
730         self._atPageArgs = ()
731         stylesheet = self.parseCSS('@page {value: 1}')
732         self.assertEqual(self._atPageArgs, ('', '', {'value': '1'}, []))
733
734         self._atPageArgs = ()
735         stylesheet = self.parseCSS('@page myPage {value: 1}')
736         self.assertEqual(self._atPageArgs, ('myPage', '', {'value': '1'}, []))
737
738         self._atPageArgs = ()
739         stylesheet = self.parseCSS('@page myPage:myPseudoPage {value: 1}')
740         self.assertEqual(self._atPageArgs, ('myPage','myPseudoPage', {'value': '1'}, []))
741
742     def testAtPageMargins(self):
743         self._atPageArgs = ()
744         stylesheet = self.parseCSS('@page {@bottom-center {value: 1} value: 8}')
745         self.assertEqual(self._atPageArgs, ('', '', {'value': '8'}, [('bottom-center', {'value': '1'})]))
746
747         self._atPageArgs = ()
748         stylesheet = self.parseCSS('@page myPage {@top {value: 1} value: 3}')
749         self.assertEqual(self._atPageArgs, ('myPage', '', {'value': '3'}, [('top', {'value': '1'})]))
750
751         self._atPageArgs = ()
752         stylesheet = self.parseCSS('@page myPage:myPseudoPage {@left {value: 2} value: 3;}')
753         self.assertEqual(self._atPageArgs, ('myPage', 'myPseudoPage', {'value': '3'}, [('left', {'value': '2'})]))
754
755     def testAtFontFace(self):
756         self._atFontFaceArgs = None
757         stylesheet = self.parseCSS('@font-face {value: 1}')
758         self.assertEqual(self._atFontFaceArgs, {'value': '1'})
759
760     def testAtIdent(self):
761         def myAtFn(cssParser, atDirective, src):
762             self._atIdentCalled = atDirective
763             return src, []
764         self.parser.atKeywordHandlers['myAtFn'] = myAtFn
765
766         self._atIdentCalled = None
767         stylesheet = self.parseCSS('@myAtFn')
768         self.assertEqual(self._atIdentCalled, 'myAtFn')
769
770 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
771 #~ Unittest Main
772 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
773
774 if __name__=='__main__':
775     unittest.main()
776
Note: See TracBrowser for help on using the browser.