summaryrefslogtreecommitdiffstats
path: root/share/extensions/tests/test_inkex_base.py
blob: 5faf7e2c468bc66866f23e458473f4a5181d0a4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# coding=utf-8
"""Test base inkex module functionality"""
from __future__ import absolute_import, print_function, unicode_literals

import os
import sys

from io import BytesIO

from inkex import AbortExtension, SvgDocumentElement
from inkex.base import InkscapeExtension, SvgThroughMixin
from inkex.tester import TestCase
from inkex.tester.mock import Capture


class ModExtension(InkscapeExtension):
    """A non-svg extension that loads, saves and flipples"""

    def effect(self):
        self.document += b">flipple"

    def load(self, stream):
        return stream.read()

    def save(self, stream):
        stream.write(self.document)


class NoModSvgExtension(SvgThroughMixin, InkscapeExtension):
    """Test the loading and not-saving of non-modified svg files"""

    def effect(self):
        return True


class ModSvgExtension(SvgThroughMixin, InkscapeExtension):
    """Test the loading and saving of svg files"""

    def effect(self):
        self.svg.set("attr", "foo")


class InkscapeExtensionTest(TestCase):
    """Tests for Inkscape Extensions"""

    effect_class = InkscapeExtension

    def setUp(self):
        self.e = self.effect_class()

    def test_bare_bones(self):
        """What happens when we don't inherit"""
        with self.assertRaises(NotImplementedError):
            self.e.run([])
        with self.assertRaises(NotImplementedError):
            prevarg = sys.argv
            sys.argv = ["pytest"]
            try:
                self.e.run()
            finally:
                sys.argv = prevarg
        with self.assertRaises(NotImplementedError):
            self.e.effect()
        with self.assertRaises(NotImplementedError):
            self.e.load(sys.stdin)
        with self.assertRaises(NotImplementedError):
            self.e.save(sys.stdout)
        self.assertEqual(self.e.name, "InkscapeExtension")

    def test_compat(self):
        """Test a few old functions and how we handle them"""
        with self.assertRaises(AttributeError):
            self.assertEqual(self.e.OptionParser, None)
        with self.assertRaises(AttributeError):
            self.assertEqual(self.e.affect(), None)

    def test_arg_parser_defaults(self):
        """Test arguments for the base class are given defaults"""
        options = self.e.arg_parser.parse_args([])
        self.assertEqual(options.input_file, None)
        self.assertEqual(options.output, None)

    def test_arg_parser_passed(self):
        """Test arguments for the base class are parsed"""
        options = self.e.arg_parser.parse_args(["--output", "foo.txt", self.empty_svg])
        self.assertEqual(options.input_file, self.empty_svg)
        self.assertEqual(options.output, "foo.txt")

    def test_get_resource(self):
        """We can get a resource path, based on where the extension is located"""
        ext = ModExtension()
        self.assertRaises(AbortExtension, ext.get_resource, "sir-not-apearing.py")

        # Test relative filename, which fails with AbortExtension if not found.
        ret = ext.get_resource(__file__)
        # Test absolute filename, which we already have, so just feed it back.
        self.assertEqual(ext.get_resource(ret), ret)

    def test_svg_path(self):
        """Can get the svg file location"""
        output = os.path.join(self.tempdir, "output.tmp")
        ext = ModExtension()
        os.environ["DOCUMENT_PATH"] = self.empty_svg
        self.assertEqual(ext.svg_path(), os.path.join(self.datadir(), "svg"))
        self.assertIn(ext.absolute_href("/foo"), ["/foo", "C:\\foo"])
        self.assertEqual(
            ext.absolute_href("./foo"), os.path.join(self.datadir(), "svg", "foo")
        )
        self.assertEqual(
            ext.absolute_href("~/foo"), os.path.realpath(os.path.expanduser("~/foo"))
        )

    def test_svg_no_path(self):
        tmp_foo = os.path.realpath("/tmp/foo")
        os.environ["DOCUMENT_PATH"] = ""
        ext = ModExtension()
        # Default results in home dir
        self.assertEqual(
            ext.absolute_href("./foo"), os.path.realpath(os.path.expanduser("~/foo"))
        )
        # Or override the default
        self.assertEqual(ext.absolute_href("./foo", "/tmp/"), tmp_foo)
        # But we can ask for errors too, this one for "document not saved"
        self.assertRaises(AbortExtension, ext.absolute_href, "./foo", default=None)
        # This covers inkscape old versions
        del os.environ["DOCUMENT_PATH"]
        self.assertRaises(AbortExtension, ext.absolute_href, "./foo", default=None)


class TestArgumentDatatypes(TestCase):
    """Test special argument types for the dataparser"""

    def test_page_descriptor(self):
        """Test that page descriptions are parsed correctly"""

        def parsetest(string, length, comparison, startvalue=1):
            result = InkscapeExtension.arg_number_ranges()
            self.assertTupleEqual(
                result(string)(length, startvalue=startvalue), comparison
            )

        parsetest("1, 2,3", 10, (1, 2, 3))
        parsetest("1-3, 5, 10", 10, (1, 2, 3, 5, 10))
        parsetest("2, 4-, 6, 7-", 10, (2, 4, 5, 6, 7, 8, 9, 10))
        parsetest("2-5, 7-9, 10-", 12, (2, 3, 4, 5, 7, 8, 9, 10, 11, 12))
        parsetest("6, 7, 8", 3, tuple())
        parsetest("2, 216-218, 10", 300, (2, 10, 216, 217, 218))
        parsetest("-3,10-,5", 12, (1, 2, 3, 5, 10, 11, 12))
        parsetest("-5, 7-", 7, (3, 4, 5, 7), 3)
        parsetest("-", 7, (), 3)


class SvgInputOutputTest(TestCase):
    """Test SVG Input Mixin"""

    def test_input_mixin(self):
        """Test svg input gets loaded"""
        obj = NoModSvgExtension()
        obj.run([self.empty_svg])
        self.assertNotEqual(obj.document, None)
        self.assertNotEqual(obj.original_document, None)

    def test_no_output(self):
        """Test svg output isn't saved when not modified"""
        obj = NoModSvgExtension()
        filename = self.temp_file(suffix=".svg")
        obj.run(["--output", filename, self.empty_svg])
        self.assertEqual(type(obj.document).__name__, "_ElementTree")
        self.assertEqual(type(obj.svg).__name__, "SvgDocumentElement")
        self.assertFalse(os.path.isfile(filename))

    def test_svg_output(self):
        """Test svg output is saved"""
        obj = ModSvgExtension()
        filename = self.temp_file(suffix=".svg")
        obj.run(["--output", filename, self.empty_svg])
        self.assertTrue(os.path.isfile(filename))
        with open(filename, "r") as fhl:
            self.assertIn("<svg", fhl.read())

    def test_str_document(self):
        """Document is saved even if it's not bytes"""
        obj = ModSvgExtension()
        obj.document = b"foo"
        obj.save(BytesIO())
        obj.document = "foo"
        ret = BytesIO()
        obj.save(ret)
        self.assertEqual(ret.getvalue(), b"foo")


class ParserTests(TestCase):
    """Test special parsing cases"""

    def test_bad_namespace(self):
        """Ignore bad namespaces, https://gitlab.com/inkscape/extensions/-/issues/465"""
        svg = (
            '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
            '<svg xmlns:ns="&amp;#38;#38;ns_ai;"></svg>'
        )
        filename = self.temp_file(suffix=".svg")
        with open(filename, "w") as file:
            file.write(svg)
        with Capture("stderr") as stderr:
            obj = NoModSvgExtension()
            obj.run([filename])
            # Test that the extension runs completely, and the document gets loaded
            self.assertTrue(isinstance(obj.svg, SvgDocumentElement))
            # Test that the error is presented to the user
            self.assertIn("is not a valid URI", stderr.getvalue())