442 lines
17 KiB
Python
442 lines
17 KiB
Python
"""Testcases for cssutils.css.CSSMediaRule"""
|
|
|
|
# flake8: noqa
|
|
|
|
import xml.dom
|
|
from . import test_cssrule
|
|
import cssutils
|
|
import pytest
|
|
|
|
|
|
class TestCSSMediaRule(test_cssrule.TestCSSRule):
|
|
def _setup_rule(self):
|
|
self.r = cssutils.css.CSSMediaRule()
|
|
self.rRO = cssutils.css.CSSMediaRule(readonly=True)
|
|
self.r_type = cssutils.css.CSSMediaRule.MEDIA_RULE
|
|
self.r_typeString = 'MEDIA_RULE'
|
|
# for tests
|
|
self.stylerule = cssutils.css.CSSStyleRule()
|
|
self.stylerule.cssText = 'a {}'
|
|
|
|
def test_init(self):
|
|
"CSSMediaRule.__init__()"
|
|
super().test_init()
|
|
|
|
r = cssutils.css.CSSMediaRule()
|
|
assert isinstance(r.cssRules, cssutils.css.CSSRuleList)
|
|
assert [] == r.cssRules
|
|
assert '' == r.cssText
|
|
assert isinstance(r.media, cssutils.stylesheets.MediaList)
|
|
assert 'all' == r.media.mediaText
|
|
assert r.name is None
|
|
|
|
r = cssutils.css.CSSMediaRule(mediaText='print', name='name')
|
|
assert isinstance(r.cssRules, cssutils.css.CSSRuleList)
|
|
assert [] == r.cssRules
|
|
assert '' == r.cssText
|
|
assert isinstance(r.media, cssutils.stylesheets.MediaList)
|
|
assert 'print' == r.media.mediaText
|
|
assert 'name' == r.name
|
|
|
|
# only possible to set @... similar name
|
|
with pytest.raises(xml.dom.InvalidModificationErr):
|
|
self.r._setAtkeyword('x')
|
|
|
|
def test_iter(self):
|
|
"CSSMediaRule.__iter__()"
|
|
m = cssutils.css.CSSMediaRule()
|
|
m.cssText = '''@media all { /*1*/a { left: 0} b{ top:0} }'''
|
|
types = [
|
|
cssutils.css.CSSRule.COMMENT,
|
|
cssutils.css.CSSRule.STYLE_RULE,
|
|
cssutils.css.CSSRule.STYLE_RULE,
|
|
]
|
|
for i, rule in enumerate(m):
|
|
assert rule == m.cssRules[i]
|
|
assert rule.type == types[i]
|
|
assert rule.parentRule == m
|
|
|
|
def test_refs(self):
|
|
"""CSSStylesheet references"""
|
|
s = cssutils.parseString('@media all {a {color: red}}')
|
|
r = s.cssRules[0]
|
|
rules = r.cssRules
|
|
assert r.cssRules[0].parentStyleSheet == s
|
|
assert rules[0].parentStyleSheet == s
|
|
|
|
# set cssText
|
|
r.cssText = '@media all {a {color: blue}}'
|
|
# not anymore: self.assertEqual(rules, r.cssRules)
|
|
|
|
# set cssRules
|
|
r.cssRules = cssutils.parseString(
|
|
'''
|
|
/**/
|
|
@x;
|
|
b {}').cssRules'''
|
|
).cssRules
|
|
# new object
|
|
assert rules != r.cssRules
|
|
for i, sr in enumerate(r.cssRules):
|
|
assert sr.parentStyleSheet == s
|
|
assert sr.parentRule == r
|
|
|
|
def test_cssRules(self):
|
|
"CSSMediaRule.cssRules"
|
|
r = cssutils.css.CSSMediaRule()
|
|
assert [] == r.cssRules
|
|
sr = cssutils.css.CSSStyleRule()
|
|
r.cssRules.append(sr)
|
|
assert [sr] == r.cssRules
|
|
ir = cssutils.css.CSSImportRule()
|
|
with pytest.raises(xml.dom.HierarchyRequestErr):
|
|
r.cssRules.append(ir)
|
|
|
|
s = cssutils.parseString('@media all { /*1*/a {x:1} }')
|
|
m = s.cssRules[0]
|
|
assert 2 == m.cssRules.length
|
|
del m.cssRules[0]
|
|
assert 1 == m.cssRules.length
|
|
m.cssRules.append('/*2*/')
|
|
assert 2 == m.cssRules.length
|
|
m.cssRules.extend(cssutils.parseString('/*3*/x {y:2}').cssRules)
|
|
assert 4 == m.cssRules.length
|
|
assert (
|
|
'@media all {\n a {\n x: 1\n }\n /*2*/\n /*3*/\n x {\n y: 2\n }\n }'
|
|
== m.cssText
|
|
)
|
|
|
|
for rule in m.cssRules:
|
|
assert rule.parentStyleSheet == s
|
|
assert rule.parentRule == m
|
|
|
|
def test_cssText(self):
|
|
"CSSMediaRule.cssText"
|
|
style = '''{
|
|
a {
|
|
color: red
|
|
}
|
|
}'''
|
|
|
|
mls = {
|
|
' (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) ': None,
|
|
' tv ': None,
|
|
' only tv ': None,
|
|
' not tv ': None,
|
|
' only tv and (color) ': None,
|
|
' only tv and(color)': ' only tv and (color) ',
|
|
' only tv and (color: red) ': None,
|
|
' only tv and (color: red) and (width: 100px) ': None,
|
|
' only tv and (color: red) and (width: 100px), tv ': None,
|
|
' only tv and (color: red) and (width: 100px), tv and (width: 20px) ': None,
|
|
' only tv and(color :red)and( width :100px ) ,tv and(width: 20px) ': ' only tv and (color: red) and (width: 100px), tv and (width: 20px) ',
|
|
' (color: red) and (width: 100px), (width: 20px) ': None,
|
|
' /*1*/ only /*2*/ tv /*3*/ and /*4*/ (/*5*/ width) /*5*/ /*6*/, (color) and (height) ': None,
|
|
'(color)and(width),(height)': ' (color) and (width), (height) ',
|
|
}
|
|
tests = {}
|
|
for b, a in list(mls.items()):
|
|
if a is None:
|
|
a = b
|
|
tests[f'@media{b}{style}'] = f'@media{a}{style}'
|
|
|
|
self.do_equal_p(tests)
|
|
self.do_equal_r(tests)
|
|
|
|
tests = {
|
|
'@media only tv{}': '',
|
|
'@media not tv{}': '',
|
|
'@media only tv and (color){}': '',
|
|
'@media only tv and (color: red){}': '',
|
|
'@media only tv and (color: red) and (width: 100px){}': '',
|
|
'@media only tv and (color: red) and (width: 100px), tv{}': '',
|
|
'@media only tv and (color: red) and (width: 100px), tv and (width: 20px){}': '',
|
|
'@media (color: red) and (width: 100px), (width: 20px){}': '',
|
|
'@media (width){}': '',
|
|
'@media (width:10px){}': '',
|
|
'@media (width), (color){}': '',
|
|
'@media (width) , (color),(height){}': '',
|
|
'@media (width) , (color) and (height){}': '',
|
|
'@media (width) and (color){}': '',
|
|
'@media all and (width){}': '',
|
|
'@media all and (width:10px){}': '',
|
|
'@media all and (width), (color){}': '',
|
|
'@media all and (width) , (color),(height){}': '',
|
|
'@media all and (width) , (color) and (height){}': '',
|
|
'@media all and (width) and (color){}': '',
|
|
'@media only tv and (width){}': '',
|
|
'@media only tv and (width:10px){}': '',
|
|
'@media only tv and (width), (color){}': '',
|
|
'@media only tv and (width) , (color),(height){}': '',
|
|
'@media only tv and (width) , (color) and (height){}': '',
|
|
'@media only tv and (width) and (color){}': '',
|
|
'@media only tv and (width) "name" {}': '',
|
|
'@media only tv and (width:10px) "name" {}': '',
|
|
'@media only tv and (width), (color){}': '',
|
|
'@media only tv and (width) , (color),(height){}': '',
|
|
'@media only tv and (width) , (color) and (height){}': '',
|
|
'@media only tv and (width) and (color){}': '',
|
|
'@media all "name"{}': '',
|
|
'@media all {}': '',
|
|
'@media/*x*/all{}': '',
|
|
'@media all { a{ x: 1} }': '@media all {\n a {\n x: 1\n }\n }',
|
|
'@media all "name" { a{ x: 1} }': '@media all "name" {\n a {\n x: 1\n }\n }',
|
|
'@MEDIA all { a{x:1} }': '@media all {\n a {\n x: 1\n }\n }',
|
|
'@\\media all { a{x:1} }': '@media all {\n a {\n x: 1\n }\n }',
|
|
'@media all {@x some;a{color: red;}b{color: green;}}': '''@media all {
|
|
@x some;
|
|
a {
|
|
color: red
|
|
}
|
|
b {
|
|
color: green
|
|
}
|
|
}''',
|
|
'@media all { @x{}}': '@media all {\n @x {\n }\n }',
|
|
'@media all "n" /**/ { @x{}}': '@media all "n" /**/ {\n @x {\n }\n }',
|
|
# comments
|
|
'@media/*1*//*2*/all/*3*//*4*/{/*5*/a{x:1}}': '@media /*1*/ /*2*/ all /*3*/ /*4*/ {\n /*5*/\n a {\n x: 1\n }\n }',
|
|
'@media /*1*/ /*2*/ all /*3*/ /*4*/ { /*5*/ a{ x: 1} }': '@media /*1*/ /*2*/ all /*3*/ /*4*/ {\n /*5*/\n a {\n x: 1\n }\n }',
|
|
# WS
|
|
'@media\n\t\f all\n\t\f {\n\t\f a{ x: 1}\n\t\f }': '@media all {\n a {\n x: 1\n }\n }',
|
|
# @page rule inside @media
|
|
'@media all { @page { margin: 0; } }': '@media all {\n @page {\n margin: 0\n }\n }',
|
|
# nested media rules
|
|
'@media all { @media all { p { color: red; } } }': '@media all {\n @media all {\n p {\n '
|
|
'color: red\n }\n }\n }',
|
|
}
|
|
self.do_equal_p(tests)
|
|
self.do_equal_r(tests)
|
|
|
|
tests = {
|
|
'@media {}': xml.dom.SyntaxErr,
|
|
'@media;': xml.dom.SyntaxErr,
|
|
'@media/*only comment*/{}': xml.dom.SyntaxErr,
|
|
'@media all;': xml.dom.SyntaxErr,
|
|
'@media all "n";': xml.dom.SyntaxErr,
|
|
'@media all; @x{}': xml.dom.SyntaxErr,
|
|
'@media { a{ x: 1} }': xml.dom.SyntaxErr,
|
|
'@media "name" { a{ x: 1} }': xml.dom.SyntaxErr,
|
|
'@media "name" all { a{ x: 1} }': xml.dom.SyntaxErr,
|
|
'@media all { @charset "x"; a{}}': xml.dom.HierarchyRequestErr,
|
|
'@media all { @import "x"; a{}}': xml.dom.HierarchyRequestErr,
|
|
'@media all { , }': xml.dom.SyntaxErr,
|
|
'@media all {}EXTRA': xml.dom.SyntaxErr,
|
|
'@media ({}': xml.dom.SyntaxErr,
|
|
'@media (color{}': xml.dom.SyntaxErr,
|
|
'@media (color:{}': xml.dom.SyntaxErr,
|
|
'@media (color:red{}': xml.dom.SyntaxErr,
|
|
'@media (:red){}': xml.dom.SyntaxErr,
|
|
'@media (:){}': xml.dom.SyntaxErr,
|
|
'@media color:red){}': xml.dom.SyntaxErr,
|
|
}
|
|
self.do_raise_p(tests)
|
|
self.do_raise_r(tests)
|
|
|
|
tests = {
|
|
# extra stuff
|
|
'@media all { x{} } a{}': xml.dom.SyntaxErr,
|
|
}
|
|
self.do_raise_r(tests)
|
|
|
|
m = cssutils.css.CSSMediaRule()
|
|
m.cssText = '''@media all {@x; /*1*/a{color: red;}}'''
|
|
for r in m.cssRules:
|
|
assert m == r.parentRule
|
|
assert m.parentStyleSheet == r.parentStyleSheet
|
|
|
|
def test_media(self):
|
|
"CSSMediaRule.media"
|
|
# see CSSImportRule.media
|
|
|
|
# setting not allowed
|
|
with pytest.raises(AttributeError):
|
|
self.r.__setattr__('media', None)
|
|
with pytest.raises(AttributeError):
|
|
self.r.__setattr__('media', 0)
|
|
|
|
# set mediaText instead
|
|
self.r.media.mediaText = 'print'
|
|
self.r.insertRule(self.stylerule)
|
|
assert '' == self.r.cssText
|
|
cssutils.ser.prefs.keepEmptyRules = True
|
|
assert '@media print {\n a {}\n }' == self.r.cssText
|
|
|
|
def test_name(self):
|
|
"CSSMediaRule.name"
|
|
r = cssutils.css.CSSMediaRule()
|
|
r.cssText = '@media all "\\n\\"ame" {a{left: 0}}'
|
|
|
|
assert '\\n"ame' == r.name
|
|
r.name = "n"
|
|
assert 'n' == r.name
|
|
assert (
|
|
'@media all "n" {\n a {\n left: 0\n }\n }' == r.cssText
|
|
)
|
|
r.name = '"'
|
|
assert '"' == r.name
|
|
assert (
|
|
'@media all "\\"" {\n a {\n left: 0\n }\n }'
|
|
== r.cssText
|
|
)
|
|
|
|
r.name = ''
|
|
assert r.name is None
|
|
assert '@media all {\n a {\n left: 0\n }\n }' == r.cssText
|
|
|
|
r.name = None
|
|
assert r.name is None
|
|
assert '@media all {\n a {\n left: 0\n }\n }' == r.cssText
|
|
|
|
with pytest.raises(xml.dom.SyntaxErr):
|
|
r._setName(0)
|
|
with pytest.raises(xml.dom.SyntaxErr):
|
|
r._setName(123)
|
|
|
|
def test_deleteRuleIndex(self):
|
|
"CSSMediaRule.deleteRule(index)"
|
|
# see CSSStyleSheet.deleteRule
|
|
m = cssutils.css.CSSMediaRule()
|
|
m.cssText = '''@media all {
|
|
@a;
|
|
/* x */
|
|
@b;
|
|
@c;
|
|
@d;
|
|
}'''
|
|
assert 5 == m.cssRules.length
|
|
with pytest.raises(xml.dom.IndexSizeErr):
|
|
m.deleteRule(5)
|
|
|
|
# end -1
|
|
# check parentRule
|
|
r = m.cssRules[-1]
|
|
assert m == r.parentRule
|
|
m.deleteRule(-1)
|
|
assert r.parentRule is None
|
|
|
|
assert 4 == m.cssRules.length
|
|
assert (
|
|
'@media all {\n @a;\n /* x */\n @b;\n @c;\n }' == m.cssText
|
|
)
|
|
# beginning
|
|
m.deleteRule(0)
|
|
assert 3 == m.cssRules.length
|
|
assert '@media all {\n /* x */\n @b;\n @c;\n }' == m.cssText
|
|
# middle
|
|
m.deleteRule(1)
|
|
assert 2 == m.cssRules.length
|
|
assert '@media all {\n /* x */\n @c;\n }' == m.cssText
|
|
# end
|
|
m.deleteRule(1)
|
|
assert 1 == m.cssRules.length
|
|
assert '@media all {\n /* x */\n }' == m.cssText
|
|
|
|
def test_deleteRule(self):
|
|
"CSSMediaRule.deleteRule(rule)"
|
|
m = cssutils.css.CSSMediaRule()
|
|
m.cssText = '''@media all {
|
|
a { color: red; }
|
|
b { color: blue; }
|
|
c { color: green; }
|
|
}'''
|
|
s1, s2, s3 = m.cssRules
|
|
|
|
r = cssutils.css.CSSStyleRule()
|
|
with pytest.raises(xml.dom.IndexSizeErr):
|
|
m.deleteRule(r)
|
|
|
|
assert 3 == m.cssRules.length
|
|
m.deleteRule(s2)
|
|
assert 2 == m.cssRules.length
|
|
assert (
|
|
m.cssText
|
|
== '@media all {\n a {\n color: red\n }\n c {\n color: green\n }\n }'
|
|
)
|
|
with pytest.raises(xml.dom.IndexSizeErr):
|
|
m.deleteRule(s2)
|
|
|
|
def test_add(self):
|
|
"CSSMediaRule.add()"
|
|
# see CSSStyleSheet.add
|
|
r = cssutils.css.CSSMediaRule()
|
|
stylerule1 = cssutils.css.CSSStyleRule()
|
|
stylerule2 = cssutils.css.CSSStyleRule()
|
|
r.add(stylerule1)
|
|
r.add(stylerule2)
|
|
assert r.cssRules[0] == stylerule1
|
|
assert r.cssRules[1] == stylerule2
|
|
|
|
def test_insertRule(self):
|
|
"CSSMediaRule.insertRule"
|
|
# see CSSStyleSheet.insertRule
|
|
r = cssutils.css.CSSMediaRule()
|
|
charsetrule = cssutils.css.CSSCharsetRule('ascii')
|
|
importrule = cssutils.css.CSSImportRule('x')
|
|
namespacerule = cssutils.css.CSSNamespaceRule()
|
|
unknownrule = cssutils.css.CSSUnknownRule('@x;')
|
|
stylerule = cssutils.css.CSSStyleRule('a')
|
|
stylerule.cssText = 'a { x: 1}'
|
|
comment1 = cssutils.css.CSSComment('/*1*/')
|
|
comment2 = cssutils.css.CSSComment('/*2*/')
|
|
|
|
# hierarchy
|
|
with pytest.raises(xml.dom.HierarchyRequestErr):
|
|
r.insertRule(charsetrule, 0)
|
|
with pytest.raises(xml.dom.HierarchyRequestErr):
|
|
r.insertRule(importrule, 0)
|
|
with pytest.raises(xml.dom.HierarchyRequestErr):
|
|
r.insertRule(namespacerule, 0)
|
|
|
|
# start insert
|
|
r.insertRule(stylerule, 0)
|
|
assert r == stylerule.parentRule
|
|
assert r.parentStyleSheet == stylerule.parentStyleSheet
|
|
# before
|
|
r.insertRule(comment1, 0)
|
|
assert r == comment1.parentRule
|
|
assert r.parentStyleSheet == stylerule.parentStyleSheet
|
|
# end explicit
|
|
r.insertRule(unknownrule, 2)
|
|
assert r == unknownrule.parentRule
|
|
assert r.parentStyleSheet == stylerule.parentStyleSheet
|
|
# end implicit
|
|
r.insertRule(comment2)
|
|
assert r == comment2.parentRule
|
|
assert r.parentStyleSheet == stylerule.parentStyleSheet
|
|
assert (
|
|
'@media all {\n /*1*/\n a {\n x: 1\n }\n @x;\n /*2*/\n }'
|
|
== r.cssText
|
|
)
|
|
|
|
# index
|
|
with pytest.raises(xml.dom.IndexSizeErr):
|
|
r.insertRule(stylerule, -1)
|
|
with pytest.raises(xml.dom.IndexSizeErr):
|
|
r.insertRule(stylerule, r.cssRules.length + 1)
|
|
|
|
def test_InvalidModificationErr(self):
|
|
"CSSMediaRule.cssText InvalidModificationErr"
|
|
self._test_InvalidModificationErr('@media')
|
|
|
|
def test_incomplete(self):
|
|
"CSSMediaRule (incomplete)"
|
|
tests = {
|
|
'@media all { @unknown;': '@media all {\n @unknown;\n }', # no }
|
|
'@media all { a {x:"1"}': '@media all {\n a {\n x: "1"\n }\n }', # no }
|
|
'@media all { a {x:"1"': '@media all {\n a {\n x: "1"\n }\n }', # no }}
|
|
'@media all { a {x:"1': '@media all {\n a {\n x: "1"\n }\n }', # no "}}
|
|
}
|
|
self.do_equal_p(tests) # parse
|
|
|
|
def test_reprANDstr(self):
|
|
"CSSMediaRule.__repr__(), .__str__()"
|
|
mediaText = 'tv, print'
|
|
|
|
s = cssutils.css.CSSMediaRule(mediaText=mediaText)
|
|
|
|
assert mediaText in str(s)
|
|
|
|
s2 = eval(repr(s))
|
|
assert isinstance(s2, s.__class__)
|
|
assert mediaText == s2.media.mediaText
|