diff options
Diffstat (limited to '')
-rw-r--r-- | share/extensions/tests/test_inkex_styles.py | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/share/extensions/tests/test_inkex_styles.py b/share/extensions/tests/test_inkex_styles.py new file mode 100644 index 0000000..68fdd87 --- /dev/null +++ b/share/extensions/tests/test_inkex_styles.py @@ -0,0 +1,235 @@ +# coding=utf-8 +""" +Test Inkex style parsing functionality. +""" + +import pytest +import warnings + +from inkex.styles import Style +from inkex.colors import Color +from inkex.tester import TestCase +from inkex.tester.svg import svg_file + + +class StyleTest(TestCase): + """Test path API and calculations""" + + def test_new_style(self): + """Create a style from a path string""" + stl = Style("border-color: blue; border-width: 4px;") + self.assertEqual(str(stl), "border-color:blue;border-width:4px") + + def test_composite(self): + """Test chaining styles together""" + stl = Style("border-color: blue;") + stl += "border-color: red; border-issues: true;" + self.assertEqual(str(stl), "border-color:red;border-issues:true") + st2 = stl + "border-issues: false;" + self.assertEqual(str(st2), "border-color:red;border-issues:false") + + def test_inbuilts(self): + """Test inbuild style functions""" + stadd = Style("a: 1") + Style("b: 2") + self.assertTrue(stadd == Style("b: 2; a: 1")) + self.assertFalse(stadd == Style("b: 2")) + self.assertFalse(stadd != Style("b: 2; a: 1")) + self.assertEqual(stadd - "a: 4", "b: 2") + stadd -= "b: 3; c: 4" + self.assertEqual(stadd, Style("a: 1")) + + def test_set_property(self): + """Set the style attribute directly""" + stl = Style() + stl["border-pain"] = "green" + self.assertEqual(str(stl), "border-pain:green") + + def test_color_property(self): + """Color special handling""" + stl = Style("fill-opacity:0.7;fill:red;") + self.assertEqual(stl.get_color("fill").alpha, 0.7) + self.assertEqual(str(stl.get_color("fill")), "rgba(255, 0, 0, 0.7)") + stl.set_color("rgba(0, 127, 0, 0.5)", "stroke") + self.assertEqual( + str(stl), "fill-opacity:0.7;fill:red;stroke-opacity:0.5;stroke:#007f00" + ) + + def test_interpolate(self): + """Test interpolation method.""" + stl1 = Style( + {"stroke-width": "0px", "fill-opacity": 1.0, "fill": Color((200, 0, 0))} + ) + stl2 = Style( + {"stroke-width": "1pc", "fill-opacity": 0.0, "fill": Color((100, 0, 100))} + ) + stl3 = stl1.interpolate(stl2, 0.5) + print(stl3) + self.assertAlmostEqual(stl3("fill-opacity"), 0.5, 1e-3) + assert stl3("fill") == [150, 0, 50] + assert stl3["stroke-width"] == "8px" + + def test_callback(self): + """Test callback.""" + calls = 0 + + def cb(style): + nonlocal calls + self.assertNotIn("fill-opacity", style) + calls += 1 + + st = Style( + {"stroke-width": "0px", "fill-opacity": 1.0, "fill": Color((200, 0, 0))}, + callback=cb, + ) + self.assertEqual(calls, 0) + st.pop("fill-opacity") + self.assertEqual(calls, 1) + + def cb(style): + nonlocal calls + self.assertEqual(style["fill-opacity"], ".75") + calls += 1 + + st.callback = cb + st["fill-opacity"] = ".75" + self.assertEqual(calls, 2) + + +class StyleSheetTest(TestCase): + """Test parsing style sheets""" + + def setUp(self): + super(StyleSheetTest, self).setUp() + self.svg = svg_file(self.data_file("svg", "css.svg")) + self.css = self.svg.stylesheet + + def test_classes(self): + """Test element class manipulation""" + rect = self.svg.getElementById("rect2") + self.assertEqual(rect.get("class"), "two") + self.assertEqual(rect.classes, ["two"]) + rect.classes[0] = "twa" + self.assertEqual(rect.get("class"), "twa") + rect.classes.append("tri") + rect.classes.append("four") + self.assertEqual(rect.get("class"), "twa tri four") + rect.classes.remove("twa") + self.assertEqual(rect.get("class"), "tri four") + rect.classes.toggle("toggle") + self.assertEqual(rect.get("class"), "tri four toggle") + rect.classes.toggle("toggle") + self.assertEqual(rect.get("class"), "tri four") + + def test_creation(self): + """Stylesheet is created when needed""" + self.svg = svg_file(self.data_file("svg", "empty.svg")) + self.assertEqual(len(self.svg.stylesheets), 0) + self.assertEqual(len(self.svg.stylesheet), 0) + self.assertEqual(len(self.svg.stylesheets), 1) + self.svg.stylesheet.append(".cls1 { fill: blue; }") + self.assertIn( + b"style><![CDATA[\n.cls1 {\n fill:blue;\n}\n]]><", self.svg.tostring() + ) + + def test_parsing(self): + """SVG parsing provides access to stylesheets""" + sheets = self.svg.stylesheets + self.assertEqual(len(sheets), 3) + self.assertEqual(len(sheets[0]), 7) + self.assertEqual(len(sheets[1]), 0) + self.assertEqual(len(sheets[2]), 2) + + def test_string(self): + """Rendered to a string""" + sheets = self.svg.stylesheets + self.assertEqual(str(sheets[0][0]), "#layer1 {\n stroke:yellow;\n}") + self.assertEqual(str(sheets[2][1]), ".rule {}") + + def test_lookup_by_id(self): + """ID CSS lookup""" + self.assertTrue( + self.css[0].to_xpath() + in ["//*[@id='layer1']", "descendant-or-self::*[@id = 'layer1']"] + ) + elem = self.svg.getElement(self.css[0].to_xpath()) + self.assertEqual(elem.get("id"), "layer1") + + def test_lookup_by_element(self): + """Element name CSS lookup""" + self.assertTrue( + self.css[1].to_xpath() in ["//svg:circle", "descendant-or-self::svg:circle"] + ) + elems = list(self.svg.xpath(self.css[1].to_xpath())) + self.assertEqual(len(elems), 2) + self.assertEqual(elems[0].get("id"), "circle1") + self.assertEqual(elems[1].get("id"), "circle2") + + def test_lookup_by_class(self): + """Class name CSS lookup""" + self.assertTrue( + self.css[2].to_xpath() + in [ + "//*[contains(concat(' ', normalize-space(@class), ' '), ' two ')]", + "descendant-or-self::*[@class and contains" + "(concat(' ', normalize-space(@class), ' '), ' two ')]", + ] + ) + elem = self.svg.getElement(self.css[2].to_xpath()) + self.assertEqual(elem.get("id"), "rect2") + + def test_lookup_and(self): + """Multiple CSS lookups""" + self.assertTrue( + self.css[3].to_xpath() + in [ + "//*[@id='rect3']" + "[contains(concat(' ', normalize-space(@class), ' '), ' three ')]", + "descendant-or-self::*[@id = 'rect3' and " + "(@class and contains(concat(' ', normalize-space(@class), ' '), ' three '))]", + ] + ) + elem = self.svg.getElement(self.css[3].to_xpath()) + self.assertEqual(elem.get("id"), "rect3") + + def test_lookup_or(self): + """SVG rules can look up the right elements""" + self.assertTrue( + self.css[6].to_xpath() + in [ + "//*[@id='circle1']|//*[@id='circle2']|" + "//*[contains(concat(' ', normalize-space(@class), ' '), ' two ')]", + "descendant-or-self::*[@id = 'circle1']|descendant-or-self::*[@id = 'circle2']" + "|descendant-or-self::*[@class and contains(concat(' ', " + "normalize-space(@class), ' '), ' two ')]", + ] + ) + elems = self.svg.xpath(self.css[6].to_xpath()) + self.assertEqual(len(elems), 3) + self.assertEqual(elems[0].get("id"), "rect2") + self.assertEqual(elems[1].get("id"), "circle1") + self.assertEqual(elems[2].get("id"), "circle2") + + def test_applied_styles(self): + """Are styles applied to the svg elements correctly""" + self.assertEqual( + str(self.svg.getElementById("rect1").cascaded_style()), "fill:blue" + ) + self.assertEqual( + str(self.svg.getElementById("rect2").cascaded_style()), + "fill:green;font:Homie", + ) + self.assertEqual( + str(self.svg.getElementById("rect3").cascaded_style()), "fill:cyan" + ) + self.assertEqual( + str(self.svg.getElementById("rect4").cascaded_style()), + "fill:grey;stroke:red", + ) + self.assertEqual( + str(self.svg.getElementById("circle1").cascaded_style()), + "fill:red;font:Homie", + ) + self.assertEqual( + str(self.svg.getElementById("circle2").cascaded_style()), + "fill:red;font:Homie", + ) |