File: //usr/local/bin/python37_/lib/python3.7/site-packages/cssutils/tests/test_cssstyledeclaration.py
"""Testcases for cssutils.css.cssstyledelaration.CSSStyleDeclaration."""
import xml.dom
from . import basetest
import cssutils
import pytest
class TestCSSStyleDeclaration(basetest.BaseTestCase):
def setup(self):
self.r = cssutils.css.CSSStyleDeclaration()
def test_init(self):
"CSSStyleDeclaration.__init__()"
s = cssutils.css.CSSStyleDeclaration()
assert '' == s.cssText
assert 0 == s.length
assert s.parentRule is None
s = cssutils.css.CSSStyleDeclaration(cssText='left: 0')
assert 'left: 0' == s.cssText
assert '0' == s.getPropertyValue('left')
sheet = cssutils.css.CSSStyleRule()
s = cssutils.css.CSSStyleDeclaration(parentRule=sheet)
assert sheet == s.parentRule
# should not be used but ordered parameter test
s = cssutils.css.CSSStyleDeclaration('top: 0', sheet)
assert 'top: 0' == s.cssText
assert sheet == s.parentRule
def test_items(self):
"CSSStyleDeclaration[CSSName]"
s = cssutils.css.CSSStyleDeclaration()
name, value, priority = 'color', 'name', ''
s[name] = value
assert value == s[name]
assert value == s.__getattribute__(name)
assert value == s.getProperty(name).value
assert priority == s.getProperty(name).priority
name, value, priority = 'UnKnown-ProPERTY', 'unknown value', 'important'
s[name] = (value, priority)
assert value == s[name]
assert value == s[name.lower()] # will be normalized
with pytest.raises(AttributeError):
s.__getattribute__(name)
assert value == s.getProperty(name).value
assert priority == s.getProperty(name).priority
name, value, priority = 'item', '1', ''
s[name] = value
assert value == s[name]
assert value == s.getProperty(name).value
assert priority == s.getProperty(name).priority
del s[name]
assert '' == s[name]
assert '' == s['never set']
def test__contains__(self):
"CSSStyleDeclaration.__contains__(nameOrProperty)"
s = cssutils.css.CSSStyleDeclaration(cssText=r'x: 1;\y: 2')
for test in ('x', r'x', 'y', r'y'):
assert test in s
assert test.upper() in s
assert cssutils.css.Property(test, '1') in s
assert 'z' not in s
assert cssutils.css.Property('z', '1') not in s
def test__iter__item(self):
"CSSStyleDeclaration.__iter__ and .item"
s = cssutils.css.CSSStyleDeclaration()
s.cssText = r'''
color: red; c\olor: blue; CO\lor: green;
left: 1px !important; left: 0;
border: 0;
'''
# __iter__
ps = []
for p in s:
ps.append((p.literalname, p.value, p.priority))
assert len(ps) == 3
assert ps[0] == (r'co\lor', 'green', '')
assert ps[1] == (r'left', '1px', 'important')
assert ps[2] == (r'border', '0', '')
# item
assert s.length == 3
assert s.item(0) == 'color'
assert s.item(1) == 'left'
assert s.item(2) == 'border'
assert s.item(10) == ''
def test_keys(self):
"CSSStyleDeclaration.keys()"
s = cssutils.parseStyle('x:1; x:2; y:1')
assert ['x', 'y'] == list(s.keys())
assert s['x'] == '2'
assert s['y'] == '1'
def test_parse(self):
"CSSStyleDeclaration parse"
# error but parse
tests = {
# property names are caseinsensitive
'TOP:0': 'top: 0',
'top:0': 'top: 0',
# simple escape
'c\\olor: red; color:green': 'color: green',
'color:g\\reen': 'color: g\\reen',
# http://www.w3.org/TR/2009/CR-CSS2-20090423/syndata.html#illegalvalues
'color:green': 'color: green',
'color:green; color': 'color: green',
'color:red; color; color:green': 'color: green',
'color:green; color:': 'color: green',
'color:red; color:; color:green': 'color: green',
'color:green; color{;color:maroon}': 'color: green',
'color:red; color{;color:maroon}; color:green': 'color: green',
# tantek hack
r'''color: red;
voice-family: "\"}\"";
voice-family:inherit;
color: green;''': 'voice-family: inherit;\ncolor: green',
r'''col\or: blue;
font-family: 'Courier New Times
color: red;
color: green;''': 'color: green',
# special IE hacks are not preserved anymore (>=0.9.5b3)
'/color: red; color: green': 'color: green',
'/ color: red; color: green': 'color: green',
'1px: red; color: green': 'color: green',
'0: red; color: green': 'color: green',
'1px:: red; color: green': 'color: green',
r'$top: 0': '',
r'$: 0': '', # really invalid!
# unknown rule but valid
'@x;\ncolor: red': None,
'@x {\n }\ncolor: red': None,
'/**/\ncolor: red': None,
'/**/\ncolor: red;\n/**/': None,
# issue #28
';color: red': 'color: red',
';;color: red;;': 'color: red',
}
cssutils.ser.prefs.keepAllProperties = False
for test, exp in list(tests.items()):
sh = cssutils.parseString('a { %s }' % test)
if exp is None:
exp = '%s' % test
elif exp != '':
exp = '%s' % exp
assert exp == sh.cssRules[0].style.cssText
cssutils.ser.prefs.useDefaults()
def test_serialize(self):
"CSSStyleDeclaration serialize"
s = cssutils.css.CSSStyleDeclaration()
tests = {
'a:1 !important; a:2;b:1': (
'a: 1 !important;\nb: 1',
'a: 1 !important;\na: 2;\nb: 1',
)
}
for test, exp in list(tests.items()):
s.cssText = test
cssutils.ser.prefs.keepAllProperties = False
assert exp[0] == s.cssText
cssutils.ser.prefs.keepAllProperties = True
assert exp[1] == s.cssText
cssutils.ser.prefs.useDefaults()
def test_children(self):
"CSSStyleDeclaration.children()"
style = '/*1*/color: red; color: green; @x;'
types = [
cssutils.css.CSSComment,
cssutils.css.Property,
cssutils.css.Property,
cssutils.css.CSSUnknownRule,
]
def t(s):
for i, x in enumerate(s.children()):
assert types[i] == type(x)
assert x.parent == s
t(cssutils.parseStyle(style))
t(cssutils.parseString('a {' + style + '}').cssRules[0].style)
t(
cssutils.parseString('@media all {a {' + style + '}}')
.cssRules[0]
.cssRules[0]
.style
)
s = cssutils.parseStyle(style)
s['x'] = '0'
assert s == s.getProperty('x').parent
s.setProperty('y', '1')
assert s == s.getProperty('y').parent
def test_cssText(self):
"CSSStyleDeclaration.cssText"
# empty
s = cssutils.css.CSSStyleDeclaration()
tests = {'': '', ' ': '', ' \t \n ': '', '/*x*/': '/*x*/'}
for test, exp in list(tests.items()):
s.cssText = 'left: 0;' # dummy to reset s
s.cssText = test
assert exp == s.cssText
# normal
s = cssutils.css.CSSStyleDeclaration()
tests = {
';': '',
'left: 0': 'left: 0',
'left:0': 'left: 0',
' left : 0 ': 'left: 0',
'left: 0;': 'left: 0',
'left: 0 !important ': 'left: 0 !important',
'left:0!important': 'left: 0 !important',
'left: 0; top: 1': 'left: 0;\ntop: 1',
# comments
# TODO: spaces?
'/*1*//*2*/left/*3*//*4*/:/*5*//*6*/0/*7*//*8*/!/*9*//*a*/important/*b*//*c*/;': '/*1*/\n/*2*/\nleft/*3*//*4*/: /*5*/ /*6*/ 0 /*7*/ /*8*/ !/*9*//*a*/important/*b*//*c*/',
'/*1*/left: 0;/*2*/ top: 1/*3*/': '/*1*/\nleft: 0;\n/*2*/\ntop: 1 /*3*/',
'left:0; top:1;': 'left: 0;\ntop: 1',
'/*1*/left: 0;/*2*/ top: 1;/*3*/': '/*1*/\nleft: 0;\n/*2*/\ntop: 1;\n/*3*/',
# WS
'left:0!important;margin:1px 2px 3px 4px!important;': 'left: 0 !important;\nmargin: 1px 2px 3px 4px !important',
'\n\r\f\t left\n\r\f\t :\n\r\f\t 0\n\r\f\t !\n\r\f\t important\n\r\f\t ;\n\r\f\t margin\n\r\f\t :\n\r\f\t 1px\n\r\f\t 2px\n\r\f\t 3px\n\r\f\t 4px;': 'left: 0 !important;\nmargin: 1px 2px 3px 4px',
}
for test, exp in list(tests.items()):
s.cssText = test
assert exp == s.cssText
# exception
tests = {
'color: #xyz': xml.dom.SyntaxErr,
'top': xml.dom.SyntaxErr,
'top:': xml.dom.SyntaxErr,
'top : ': xml.dom.SyntaxErr,
'top:!important': xml.dom.SyntaxErr,
'top:!important;': xml.dom.SyntaxErr,
'top:;': xml.dom.SyntaxErr,
'top 0': xml.dom.SyntaxErr,
'top 0;': xml.dom.SyntaxErr,
':': xml.dom.SyntaxErr,
':0': xml.dom.SyntaxErr,
':0;': xml.dom.SyntaxErr,
':0!important': xml.dom.SyntaxErr,
':;': xml.dom.SyntaxErr,
': ;': xml.dom.SyntaxErr,
':!important;': xml.dom.SyntaxErr,
': !important;': xml.dom.SyntaxErr,
'0': xml.dom.SyntaxErr,
'0!important': xml.dom.SyntaxErr,
'0!important;': xml.dom.SyntaxErr,
'0;': xml.dom.SyntaxErr,
'!important': xml.dom.SyntaxErr,
'!important;': xml.dom.SyntaxErr,
}
self.do_raise_r(tests)
def test_getCssText(self):
"CSSStyleDeclaration.getCssText(separator)"
s = cssutils.css.CSSStyleDeclaration(cssText='a:1;b:2')
assert 'a: 1;\nb: 2' == s.getCssText()
assert 'a: 1;b: 2' == s.getCssText(separator='')
assert 'a: 1;/*x*/b: 2' == s.getCssText(separator='/*x*/')
def test_parentRule(self):
"CSSStyleDeclaration.parentRule"
s = cssutils.css.CSSStyleDeclaration()
sheet = cssutils.css.CSSStyleRule()
s.parentRule = sheet
assert sheet == s.parentRule
sheet = cssutils.parseString('a{x:1}')
s = sheet.cssRules[0]
d = s.style
assert s == d.parentRule
s = cssutils.parseString(
'''
@font-face {
font-weight: bold;
}
a {
font-weight: bolder;
}
@page {
font-weight: bolder;
}
'''
)
for r in s:
assert r.style.parentRule == r
def test_getProperty(self):
"CSSStyleDeclaration.getProperty"
s = cssutils.css.CSSStyleDeclaration()
s.cssText = r'''
color: red; c\olor: blue; CO\lor: green;
left: 1px !important; left: 0;
border: 0;
'''
assert s.getProperty('color').cssText == r'co\lor: green'
assert s.getProperty(r'COLO\r').cssText == r'co\lor: green'
assert s.getProperty('left').cssText == r'left: 1px !important'
assert s.getProperty('border').cssText == r'border: 0'
def test_getProperties(self):
"CSSStyleDeclaration.getProperties()"
s = cssutils.css.CSSStyleDeclaration(
cssText='/*1*/y:0;x:a !important;y:1; \\x:b;'
)
tests = {
# name, all
(None, False): [('y', '1', ''), ('x', 'a', 'important')],
(None, True): [
('y', '0', ''),
('x', 'a', 'important'),
('y', '1', ''),
('\\x', 'b', ''),
],
('x', False): [('x', 'a', 'important')],
('\\x', False): [('x', 'a', 'important')],
('x', True): [('x', 'a', 'important'), ('\\x', 'b', '')],
('\\x', True): [('x', 'a', 'important'), ('\\x', 'b', '')],
}
for test in tests:
name, all = test
expected = tests[test]
actual = s.getProperties(name, all)
assert len(expected) == len(actual)
for i, ex in enumerate(expected):
a = actual[i]
assert ex == (a.literalname, a.value, a.priority)
# order is be effective properties set
s = cssutils.css.CSSStyleDeclaration(cssText='a:0;b:1;a:1')
assert 'ba' == ''.join([p.name for p in s])
def test_getPropertyCSSValue(self):
"CSSStyleDeclaration.getPropertyCSSValue()"
s = cssutils.css.CSSStyleDeclaration(cssText='color: red;c\\olor: green')
assert 'green' == s.getPropertyCSSValue('color').cssText
assert 'green' == s.getPropertyCSSValue('c\\olor').cssText
assert 'red' == s.getPropertyCSSValue('color', False).cssText
assert 'green' == s.getPropertyCSSValue('c\\olor', False).cssText
# # shorthand CSSValue should be None
# SHORTHAND = [
# u'background',
# u'border',
# u'border-left', u'border-right',
# u'border-top', u'border-bottom',
# u'border-color', u'border-style', u'border-width',
# u'cue',
# u'font',
# u'list-style',
# u'margin',
# u'outline',
# u'padding',
# u'pause']
# for short in SHORTHAND:
# s.setProperty(short, u'inherit')
# self.assertEqual(None, s.getPropertyCSSValue(short))
def test_getPropertyValue(self):
"CSSStyleDeclaration.getPropertyValue()"
s = cssutils.css.CSSStyleDeclaration()
assert '' == s.getPropertyValue('unset')
s.setProperty('left', '0')
assert '0' == s.getPropertyValue('left')
s.setProperty('border', '1px solid green')
assert '1px solid green' == s.getPropertyValue('border')
s = cssutils.css.CSSStyleDeclaration(cssText='color: red;c\\olor: green')
assert 'green' == s.getPropertyValue('color')
assert 'green' == s.getPropertyValue('c\\olor')
assert 'red' == s.getPropertyValue('color', False)
assert 'green' == s.getPropertyValue('c\\olor', False)
tests = {
r'color: red; color: green': 'green',
r'c\olor: red; c\olor: green': 'green',
r'color: red; c\olor: green': 'green',
r'color: red !important; color: green !important': 'green',
r'color: green !important; color: red': 'green',
}
for test in tests:
s = cssutils.css.CSSStyleDeclaration(cssText=test)
assert tests[test] == s.getPropertyValue('color')
def test_getPropertyPriority(self):
"CSSStyleDeclaration.getPropertyPriority()"
s = cssutils.css.CSSStyleDeclaration()
assert '' == s.getPropertyPriority('unset')
s.setProperty('left', '0', '!important')
assert 'important' == s.getPropertyPriority('left')
s = cssutils.css.CSSStyleDeclaration(
cssText='x: 1 !important;\\x: 2;x: 3 !important;\\x: 4'
)
assert 'important' == s.getPropertyPriority('x')
assert 'important' == s.getPropertyPriority('\\x')
assert 'important' == s.getPropertyPriority('x', True)
assert '' == s.getPropertyPriority('\\x', False)
def test_removeProperty(self):
"CSSStyleDeclaration.removeProperty()"
cssutils.ser.prefs.useDefaults()
s = cssutils.css.CSSStyleDeclaration()
css = r'\x:0 !important; x:1; \x:2; x:3'
# normalize=True DEFAULT
s.cssText = css
assert '0' == s.removeProperty('x')
assert '' == s.cssText
# normalize=False
s.cssText = css
assert '3' == s.removeProperty('x', normalize=False)
assert r'\x: 0 !important;\x: 2' == s.getCssText(separator='')
assert '0' == s.removeProperty(r'\x', normalize=False)
assert '' == s.cssText
s.cssText = css
assert '0' == s.removeProperty(r'\x', normalize=False)
assert r'x: 1;x: 3' == s.getCssText(separator='')
assert '3' == s.removeProperty('x', normalize=False)
assert '' == s.cssText
def test_setProperty(self):
"CSSStyleDeclaration.setProperty()"
s = cssutils.css.CSSStyleDeclaration()
s.setProperty('top', '0', '!important')
assert '0' == s.getPropertyValue('top')
assert 'important' == s.getPropertyPriority('top')
s.setProperty('top', '1px')
assert '1px' == s.getPropertyValue('top')
assert '' == s.getPropertyPriority('top')
s.setProperty('top', '2px')
assert '2px' == s.getPropertyValue('top')
s.setProperty('\\top', '3px')
assert '3px' == s.getPropertyValue('top')
s.setProperty('\\top', '4px', normalize=False)
assert '4px' == s.getPropertyValue('top')
assert '4px' == s.getPropertyValue('\\top', False)
assert '3px' == s.getPropertyValue('top', False)
# case insensitive
s.setProperty('TOP', '0', '!IMPORTANT')
assert '0' == s.getPropertyValue('top')
assert 'important' == s.getPropertyPriority('top')
tests = {
('left', '0', ''): 'left: 0',
('left', '0', 'important'): 'left: 0 !important',
('LEFT', '0', 'important'): 'left: 0 !important',
('left', '0', 'important'): 'left: 0 !important',
}
for test, exp in list(tests.items()):
s = cssutils.css.CSSStyleDeclaration()
n, v, p = test
s.setProperty(n, v, p)
assert exp == s.cssText
assert v == s.getPropertyValue(n)
assert p == s.getPropertyPriority(n)
# empty
s = cssutils.css.CSSStyleDeclaration()
assert '' == s.top
s.top = '0'
assert '0' == s.top
s.top = ''
assert '' == s.top
s.top = None
assert '' == s.top
def test_setProperty2(self):
"CSSStyleDeclaration.setProperty(replace=)"
s = cssutils.css.CSSStyleDeclaration()
s.setProperty('top', '1px')
assert len(s.getProperties('top', all=True)) == 1
s.setProperty('top', '2px')
assert len(s.getProperties('top', all=True)) == 1
assert s.getPropertyValue('top') == '2px'
s.setProperty('top', '3px', replace=False)
assert len(s.getProperties('top', all=True)) == 2
assert s.getPropertyValue('top') == '3px'
def test_length(self):
"CSSStyleDeclaration.length"
s = cssutils.css.CSSStyleDeclaration()
# cssText
s.cssText = 'left: 0'
assert 1 == s.length
assert 1 == len(s.seq)
s.cssText = '/*1*/left/*x*/:/*x*/0/*x*/;/*2*/ top: 1;/*3*/'
assert 2 == s.length
assert 5 == len(s.seq)
# set
s = cssutils.css.CSSStyleDeclaration()
s.setProperty('top', '0', '!important')
assert 1 == s.length
s.setProperty('top', '1px')
assert 1 == s.length
s.setProperty('left', '1px')
def test_nameParameter(self):
"CSSStyleDeclaration.XXX(name)"
s = cssutils.css.CSSStyleDeclaration()
s.setProperty('top', '1px', '!important')
assert '1px' == s.getPropertyValue('top')
assert '1px' == s.getPropertyValue('TOP')
assert '1px' == s.getPropertyValue(r'T\op')
assert 'important' == s.getPropertyPriority('top')
assert 'important' == s.getPropertyPriority('TOP')
assert 'important' == s.getPropertyPriority(r'T\op')
s.setProperty('top', '2px', '!important')
assert '2px' == s.removeProperty('top')
s.setProperty('top', '2px', '!important')
assert '2px' == s.removeProperty('TOP')
s.setProperty('top', '2px', '!important')
assert '2px' == s.removeProperty(r'T\op')
def test_css2properties(self):
"CSSStyleDeclaration.$css2property get set del"
s = cssutils.css.CSSStyleDeclaration(
cssText='left: 1px;color: red; font-style: italic'
)
s.color = 'green'
s.fontStyle = 'normal'
assert 'green' == s.color
assert 'normal' == s.fontStyle
assert 'green' == s.getPropertyValue('color')
assert 'normal' == s.getPropertyValue('font-style')
assert '''left: 1px;\ncolor: green;\nfont-style: normal''' == s.cssText
del s.color
assert '''left: 1px;\nfont-style: normal''' == s.cssText
del s.fontStyle
assert 'left: 1px' == s.cssText
with pytest.raises(AttributeError):
s.__setattr__('UNKNOWN', 'red')
# unknown properties must be set with setProperty!
s.setProperty('UNKNOWN', 'red')
# but are still not usable as property!
with pytest.raises(AttributeError):
s.__getattribute__('UNKNOWN')
with pytest.raises(AttributeError):
s.__delattr__('UNKNOWN')
# but are kept
assert 'red' == s.getPropertyValue('UNKNOWN')
assert '''left: 1px;\nunknown: red''' == s.cssText
def test_reprANDstr(self):
"CSSStyleDeclaration.__repr__(), .__str__()"
s = cssutils.css.CSSStyleDeclaration(cssText='a:1;b:2')
assert "2" in str(s) # length
s2 = eval(repr(s))
assert isinstance(s2, s.__class__)
def test_valid(self):
"CSSStyleDeclaration.valid"
cases = [
('color: red;', True),
('color: asd;', False),
('foo: red;', False),
('color: red; foo: red;', False),
]
for case, expected in cases:
s = cssutils.css.CSSStyleDeclaration(cssText=case)
msg = '{!r} should be {}'.format(case, 'valid' if expected else 'invalid')
assert s.valid == expected, msg