1# Copyright (c) 2020 Ultimaker B.V.
2# Uranium is released under the terms of the LGPLv3 or higher.
3import re
4from unittest import TestCase
5from unittest.mock import patch
6from urllib.parse import urlparse
7
8from UM.Qt.Bindings.Utilities import UrlUtil
9
10from io import StringIO
11
12
13class TestUrlUtil(TestCase):
14
15    def setUp(self) -> None:
16        self.url_util = UrlUtil()
17
18    def test_urlHasValidScheme_url_scheme_valid_and_in_allowed_schemes(self):
19        """
20        Tests the happy scenario. When the scheme of the url is a valid scheme (http or https) and it is
21        in the allowed schemes.
22
23        :return: None
24        """
25        self.assertTrue(self.url_util._urlHasValidScheme("https://www.ultimaker.com", ["https"]))
26        self.assertTrue(self.url_util._urlHasValidScheme("http://www.angusj.com/delphi/clipper.php", ["http"]))
27        self.assertTrue(self.url_util._urlHasValidScheme("http://www.angusj.com/delphi/clipper.php", ["http", "https"]))
28
29    def test_urlHasValidScheme_allowed_invalid_scheme_generates_warning(self):
30        """
31        Tests the following unhappy scenario:
32        If we try to allow an invalid scheme when calling the function (anything other than http or https), then a
33        warning message that mentions all the invalid schemes should be generated in the console.
34        This warning message lets the developer know that he/she is trying to allow an invalid scheme.
35
36        :return: None
37        """
38        invalid_schemes = [["mailto"], ["ftp"], ["blue", "potato"]]
39        for schemes_list in invalid_schemes:
40            with patch('sys.stdout', new=StringIO()) as mock_output:  # re-routes the output inside mock_output
41                allowed_schemes = ["https"]
42                allowed_schemes.extend(schemes_list)
43                self.url_util._urlHasValidScheme("https://www.ultimaker.com", allowed_schemes)
44
45                # Ensure the correct message is outputted in the console
46                expected_output = re.sub(r'\W+', ' ', "Attempted to allow invalid schemes")  # remove special characters
47                console_ouput = re.sub(r'\W+', ' ', mock_output.getvalue().strip())
48                self.assertIn(expected_output, console_ouput)  # Assert the correct message is in the console output
49                for scheme in schemes_list:
50                    self.assertIn(scheme, console_ouput)  # Assert each of the schemes that are being tested appears in the console output
51
52    def test_urlHasValidScheme_url_scheme_not_in_allowed_schemes(self):
53        """
54        Tests the following unhappy scenario:
55        If the function tries to open a URL with a scheme that is not allowed, the function should generate an error
56        message indicating that the url has a disallowed scheme.
57
58        :return:
59        """
60        invalid_combinations = (("https://www.ultimaker.com", ["http"]), ("http://www.ultimaker.com", ["https"]))
61        for url, allowed_schemes in invalid_combinations:
62            with patch('sys.stdout', new=StringIO()) as mock_output:  # re-routes the output inside mock_output
63
64                # Ensure the function fails
65                self.assertFalse(self.url_util._urlHasValidScheme(url, allowed_schemes))
66
67                # Ensure the correct message is outputted in the console
68                expected_output = "The scheme '{scheme}' is not in the allowed schemes".format(scheme = urlparse(url).scheme)
69                expected_output = re.sub(r'\W+', ' ', expected_output)  # remove special characters
70                console_ouput = mock_output.getvalue().strip()
71                console_ouput = re.sub(r'\W+', ' ', console_ouput)  # remove special characters
72                self.assertIn(expected_output, console_ouput)
73                for scheme in allowed_schemes:
74                    self.assertIn(scheme, console_ouput)
75
76