593 lines
22 KiB
Python
593 lines
22 KiB
Python
"""Testcases for cssutils.css.cssstyledelaration.CSSStyleDeclaration."""
|
|
|
|
import xml.dom
|
|
from . import basetest
|
|
import cssutils
|
|
import pytest
|
|
|
|
|
|
class TestCSSStyleDeclaration(basetest.BaseTestCase):
|
|
def setup_method(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
|
|
|
|
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
|
|
|
|
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()"
|
|
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',
|
|
}
|
|
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
|