1from io import BytesIO
2
3import pytest
4
5from translate.convert import po2ical, test_convert
6
7
8class TestPO2Ical:
9
10    ConverterClass = po2ical.po2ical
11
12    def _convert(
13        self,
14        input_string,
15        template_string=None,
16        include_fuzzy=False,
17        output_threshold=None,
18        success_expected=True,
19    ):
20        """Helper that converts to target format without using files."""
21        input_file = BytesIO(input_string.encode())
22        output_file = BytesIO()
23        template_file = None
24        if template_string:
25            template_file = BytesIO(template_string.encode())
26        expected_result = 1 if success_expected else 0
27        converter = self.ConverterClass(
28            input_file, output_file, template_file, include_fuzzy, output_threshold
29        )
30        assert converter.run() == expected_result
31        return None, output_file
32
33    def _convert_to_string(self, *args, **kwargs):
34        """Helper that converts to target format string without using files."""
35        return self._convert(*args, **kwargs)[1].getvalue().decode("utf-8")
36
37    def test_convert_empty_file(self):
38        """Check that an empty PO converts to valid iCalendar."""
39        input_string = ""
40        icalendar_boilerplate = """BEGIN:VCALENDAR
41VERSION:2.0
42PRODID:-//hacksw/handcal//NONSGML v1.0//EN
43BEGIN:VEVENT
44UID:uid1@example.com
45DTSTART:19970714T170000Z
46DTEND:19970715T035959Z
47DTSTAMP:19970714T170000Z
48ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
49SUMMARY:%s
50END:VEVENT
51END:VCALENDAR
52""".replace(
53            "\n", "\r\n"
54        )
55        template_string = icalendar_boilerplate % "Value"
56        expected_output = icalendar_boilerplate % "Value"
57        assert expected_output == self._convert_to_string(input_string, template_string)
58
59    def test_summary(self):
60        """Check that a simple PO converts valid iCalendar SUMMARY."""
61        input_string = """
62#: [uid1@example.com]SUMMARY
63msgid "Value"
64msgstr "Waarde"
65"""
66        icalendar_boilerplate = """BEGIN:VCALENDAR
67VERSION:2.0
68PRODID:-//hacksw/handcal//NONSGML v1.0//EN
69BEGIN:VEVENT
70UID:uid1@example.com
71DTSTART:19970714T170000Z
72DTEND:19970715T035959Z
73DTSTAMP:19970714T170000Z
74ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
75SUMMARY:%s
76END:VEVENT
77END:VCALENDAR
78""".replace(
79            "\n", "\r\n"
80        )
81        template_string = icalendar_boilerplate % "Value"
82        expected_output = icalendar_boilerplate % "Waarde"
83        assert expected_output == self._convert_to_string(input_string, template_string)
84
85    def test_description(self):
86        """Check that a simple PO converts valid iCalendar DESCRIPTION."""
87        input_string = """
88#: [uid1@example.com]DESCRIPTION
89msgid "My description"
90msgstr "A miña descrición"
91"""
92        icalendar_boilerplate = """BEGIN:VCALENDAR
93VERSION:2.0
94PRODID:-//hacksw/handcal//NONSGML v1.0//EN
95BEGIN:VEVENT
96UID:uid1@example.com
97DTSTART:19970714T170000Z
98DTEND:19970715T035959Z
99DESCRIPTION:%s
100DTSTAMP:19970714T170000Z
101ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
102END:VEVENT
103END:VCALENDAR
104""".replace(
105            "\n", "\r\n"
106        )
107        template_string = icalendar_boilerplate % "My description"
108        expected_output = icalendar_boilerplate % "A miña descrición"
109        assert expected_output == self._convert_to_string(input_string, template_string)
110
111    def test_location(self):
112        """Check that a simple PO converts valid iCalendar LOCATION."""
113        input_string = """
114#: [uid1@example.com]LOCATION
115msgid "The location"
116msgstr "O lugar"
117"""
118        icalendar_boilerplate = """BEGIN:VCALENDAR
119VERSION:2.0
120PRODID:-//hacksw/handcal//NONSGML v1.0//EN
121BEGIN:VEVENT
122UID:uid1@example.com
123DTSTART:19970714T170000Z
124DTEND:19970715T035959Z
125DTSTAMP:19970714T170000Z
126LOCATION:%s
127ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
128END:VEVENT
129END:VCALENDAR
130""".replace(
131            "\n", "\r\n"
132        )
133        template_string = icalendar_boilerplate % "The location"
134        expected_output = icalendar_boilerplate % "O lugar"
135        assert expected_output == self._convert_to_string(input_string, template_string)
136
137    def test_comment(self):
138        """Check that a simple PO converts valid iCalendar COMMENT."""
139        input_string = """
140#: [uid1@example.com]COMMENT
141msgid "Some comment"
142msgstr "Comentarios ao chou"
143"""
144        icalendar_boilerplate = """BEGIN:VCALENDAR
145VERSION:2.0
146PRODID:-//hacksw/handcal//NONSGML v1.0//EN
147BEGIN:VEVENT
148UID:uid1@example.com
149DTSTART:19970714T170000Z
150DTEND:19970715T035959Z
151COMMENT:%s
152DTSTAMP:19970714T170000Z
153ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
154END:VEVENT
155END:VCALENDAR
156""".replace(
157            "\n", "\r\n"
158        )
159        template_string = icalendar_boilerplate % "Some comment"
160        expected_output = icalendar_boilerplate % "Comentarios ao chou"
161        assert expected_output == self._convert_to_string(input_string, template_string)
162
163    def test_complex_icalendar(self):
164        """Check that a PO converts valid iCalendar."""
165        input_string = """
166#: [uid1@example.com]SUMMARY
167msgid "My summary"
168msgstr "Resumo"
169
170#: [uid1@example.com]DESCRIPTION
171msgid "My description"
172msgstr "A miña descrición"
173
174#: [uid1@example.com]LOCATION
175msgid "The location"
176msgstr "O lugar"
177
178#: [uid1@example.com]COMMENT
179msgid "Some comment"
180msgstr "Comentarios ao chou"
181"""
182        icalendar_boilerplate = """BEGIN:VCALENDAR
183VERSION:2.0
184PRODID:-//hacksw/handcal//NONSGML v1.0//EN
185BEGIN:VEVENT
186UID:uid1@example.com
187DTSTART:19970714T170000Z
188DTEND:19970715T035959Z
189COMMENT:%s
190DESCRIPTION:%s
191DTSTAMP:19970714T170000Z
192LOCATION:%s
193ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
194SUMMARY:%s
195END:VEVENT
196END:VCALENDAR
197""".replace(
198            "\n", "\r\n"
199        )
200        template_string = icalendar_boilerplate % (
201            "Some comment",
202            "My description",
203            "The location",
204            "My summary",
205        )
206        expected_output = icalendar_boilerplate % (
207            "Comentarios ao chou",
208            "A miña descrición",
209            "O lugar",
210            "Resumo",
211        )
212        assert expected_output == self._convert_to_string(input_string, template_string)
213
214    def test_convert_skip_fuzzy(self):
215        """Check that by default fuzzy units are converted with source text."""
216        input_string = """
217#, fuzzy
218#: [uid1@example.com]SUMMARY
219msgid "Value"
220msgstr "Waarde"
221"""
222        icalendar_boilerplate = """BEGIN:VCALENDAR
223VERSION:2.0
224PRODID:-//hacksw/handcal//NONSGML v1.0//EN
225BEGIN:VEVENT
226UID:uid1@example.com
227DTSTART:19970714T170000Z
228DTEND:19970715T035959Z
229DTSTAMP:19970714T170000Z
230ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
231SUMMARY:%s
232END:VEVENT
233END:VCALENDAR
234""".replace(
235            "\n", "\r\n"
236        )
237        template_string = icalendar_boilerplate % "Value"
238        expected_output = icalendar_boilerplate % "Value"
239        assert expected_output == self._convert_to_string(input_string, template_string)
240
241    def test_convert_include_fuzzy(self):
242        """Check fuzzy units are converted with target text if specified."""
243        input_string = """
244#, fuzzy
245#: [uid1@example.com]SUMMARY
246msgid "Value"
247msgstr "Waarde"
248"""
249        icalendar_boilerplate = """BEGIN:VCALENDAR
250VERSION:2.0
251PRODID:-//hacksw/handcal//NONSGML v1.0//EN
252BEGIN:VEVENT
253UID:uid1@example.com
254DTSTART:19970714T170000Z
255DTEND:19970715T035959Z
256DTSTAMP:19970714T170000Z
257ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
258SUMMARY:%s
259END:VEVENT
260END:VCALENDAR
261""".replace(
262            "\n", "\r\n"
263        )
264        template_string = icalendar_boilerplate % "Value"
265        expected_output = icalendar_boilerplate % "Waarde"
266        assert expected_output == self._convert_to_string(
267            input_string, template_string, include_fuzzy=True
268        )
269
270    def test_no_template(self):
271        """Check that a template is required."""
272        with pytest.raises(ValueError):
273            self._convert_to_string("")
274
275    def test_template_location_not_in_source_file(self):
276        """Check conversion when template unit is not in source file."""
277        input_string = """
278#: [NOT_IN_TEMPLATE]SUMMARY
279msgid "Value"
280msgstr "Waarde"
281"""
282        icalendar_boilerplate = """BEGIN:VCALENDAR
283VERSION:2.0
284PRODID:-//hacksw/handcal//NONSGML v1.0//EN
285BEGIN:VEVENT
286UID:uid1@example.com
287DTSTART:19970714T170000Z
288DTEND:19970715T035959Z
289DTSTAMP:19970714T170000Z
290ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
291SUMMARY:%s
292END:VEVENT
293END:VCALENDAR
294""".replace(
295            "\n", "\r\n"
296        )
297        template_string = icalendar_boilerplate % "Random"
298        expected_output = icalendar_boilerplate % "Random"
299        assert expected_output == self._convert_to_string(input_string, template_string)
300
301    def test_convert_completion_below_threshold(self):
302        """Check no conversion if input completion is below threshold."""
303        input_string = """
304#: [uid1@example.com]SUMMARY
305msgid "Value"
306msgstr ""
307"""
308        icalendar_boilerplate = """BEGIN:VCALENDAR
309VERSION:2.0
310PRODID:-//hacksw/handcal//NONSGML v1.0//EN
311BEGIN:VEVENT
312UID:uid1@example.com
313DTSTART:19970714T170000Z
314DTEND:19970715T035959Z
315DTSTAMP:19970714T170000Z
316ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
317SUMMARY:%s
318END:VEVENT
319END:VCALENDAR
320""".replace(
321            "\n", "\r\n"
322        )
323        template_string = icalendar_boilerplate % "Value"
324        expected_output = ""
325        # Input completion is 0% so with a 70% threshold it should not output.
326        output = self._convert_to_string(
327            input_string, template_string, output_threshold=70, success_expected=False
328        )
329        assert output == expected_output
330
331    def test_convert_completion_above_threshold(self):
332        """Check there is conversion if input completion is above threshold."""
333        input_string = """
334#: [uid1@example.com]SUMMARY
335msgid "Value"
336msgstr "Waarde"
337"""
338        icalendar_boilerplate = """BEGIN:VCALENDAR
339VERSION:2.0
340PRODID:-//hacksw/handcal//NONSGML v1.0//EN
341BEGIN:VEVENT
342UID:uid1@example.com
343DTSTART:19970714T170000Z
344DTEND:19970715T035959Z
345DTSTAMP:19970714T170000Z
346ORGANIZER;CN=John Doe:MAILTO:john.doe@example.com
347SUMMARY:%s
348END:VEVENT
349END:VCALENDAR
350""".replace(
351            "\n", "\r\n"
352        )
353        template_string = icalendar_boilerplate % "Value"
354        expected_output = icalendar_boilerplate % "Waarde"
355        # Input completion is 100% so with a 70% threshold it should output.
356        output = self._convert_to_string(
357            input_string, template_string, output_threshold=70
358        )
359        assert output == expected_output
360
361
362class TestPO2IcalCommand(test_convert.TestConvertCommand, TestPO2Ical):
363    """Tests running actual po2ical commands on files"""
364
365    convertmodule = po2ical
366    defaultoptions = {"progress": "none"}
367
368    def test_help(self, capsys):
369        """tests getting help"""
370        options = super().test_help(capsys)
371        options = self.help_check(options, "-t TEMPLATE, --template=TEMPLATE")
372        options = self.help_check(options, "--threshold=PERCENT")
373        options = self.help_check(options, "--fuzzy")
374        options = self.help_check(options, "--nofuzzy", last=True)
375