Passed
Pull Request — develop (#458)
by
unknown
02:49
created

TestShow.test_show_hidden()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
"""Unit tests for the doorstop.cli.utilities module."""
2
3
import unittest
4
from unittest.mock import patch, Mock
5
from argparse import ArgumentTypeError
6
7
from doorstop.cli import utilities
8
from doorstop import common
9
from doorstop import settings
10
11
from doorstop.cli.test import SettingsTestCase
12
13
14
class TestCapture(unittest.TestCase):
15
16
    """Unit tests for the `Capture` class."""
17
18
    def test_success(self):
19
        """Verify a success can be captured."""
20
        with utilities.capture() as success:
21
            pass  # no exception raised
22
        self.assertTrue(success)
23
24
    def test_failure(self):
25
        """Verify a failure can be captured."""
26
        with utilities.capture() as success:
27
            raise common.DoorstopError
28
        self.assertFalse(success)
29
30
    def test_failure_uncaught(self):
31
        """Verify a failure can be left uncaught."""
32
        try:
33
            with utilities.capture(catch=False) as success:
34
                raise common.DoorstopError
35
        except common.DoorstopError:
36
            self.assertFalse(success)
37
        else:
38
            self.fail("DoorstopError not raised")
39
40
41
class TestConfigureSettings(SettingsTestCase):
42
43
    """Unit tests for the `configure_settings` function."""
44
45
    def test_configure_settings(self):
46
        """Verify settings are parsed correctly."""
47
        args = Mock()
48
        args.reorder = False
49
        utilities.configure_settings(args)
50
        self.assertFalse(settings.REFORMAT)
51
        self.assertFalse(settings.REORDER)
52
        self.assertFalse(settings.CHECK_LEVELS)
53
        self.assertFalse(settings.CHECK_REF)
54
        self.assertFalse(settings.CHECK_CHILD_LINKS)
55
        self.assertFalse(settings.PUBLISH_CHILD_LINKS)
56
        self.assertFalse(settings.CHECK_SUSPECT_LINKS)
57
        self.assertFalse(settings.CHECK_REVIEW_STATUS)
58
        self.assertFalse(settings.PUBLISH_BODY_LEVELS)
59
        self.assertFalse(settings.WARN_ALL)
60
        self.assertFalse(settings.ERROR_ALL)
61
62
63
class TestLiteralEval(unittest.TestCase):
64
65
    """Unit tests for the `literal_eval` function."""
66
67
    def test_literal_eval(self):
68
        """Verify a string can be evaluated as a Python literal."""
69
        self.assertEqual(42.0, utilities.literal_eval("42.0"))
70
71
    def test_literal_eval_invalid_err(self):
72
        """Verify an invalid literal calls the error function."""
73
        error = Mock()
74
        utilities.literal_eval("1/", error=error)
75
        self.assertEqual(1, error.call_count)
76
77
    @patch('doorstop.cli.utilities.log.critical')
78
    def test_literal_eval_invalid_log(self, mock_log):
79
        """Verify an invalid literal logs an error."""
80
        utilities.literal_eval("1/")
81
        self.assertEqual(1, mock_log.call_count)
82
83
84
class TestGetExt(unittest.TestCase):
85
86
    """Unit tests for the `get_ext` function."""
87
88
    def test_get_ext_stdout_document(self):
89
        """Verify a default output extension can be selected."""
90
        args = Mock(spec=[])
91
        error = Mock()
92
        # Act
93
        ext = utilities.get_ext(args, error, '.out', '.file')
94
        # Assert
95
        self.assertEqual(0, error.call_count)
96
        self.assertEqual('.out', ext)
97
98
    def test_get_ext_stdout_document_override(self):
99
        """Verify a default output extension can be overridden."""
100
        args = Mock(spec=['html'])
101
        args.html = True
102
        error = Mock()
103
        # Act
104
        ext = utilities.get_ext(args, error, '.out', '.file')
105
        # Assert
106
        self.assertEqual(0, error.call_count)
107
        self.assertEqual('.html', ext)
108
109
    @patch('os.path.isdir', Mock(return_value=True))
110
    def test_get_ext_file_document_to_directory(self):
111
        """Verify a path is required for a single document."""
112
        args = Mock(spec=['path'])
113
        args.path = 'path/to/directory'
114
        error = Mock()
115
        # Act
116
        utilities.get_ext(args, error, '.out', '.file')
117
        # Assert
118
        self.assertNotEqual(0, error.call_count)
119
120
    def test_get_ext_file_document(self):
121
        """Verify a specified file extension can be selected."""
122
        args = Mock(spec=['path'])
123
        args.path = 'path/to/file.cust'
124
        error = Mock()
125
        # Act
126
        ext = utilities.get_ext(args, error, '.out', '.file')
127
        # Assert
128
        self.assertEqual(0, error.call_count)
129
        self.assertEqual('.cust', ext)
130
131
    def test_get_ext_file_tree(self):
132
        """Verify a specified file extension can be selected."""
133
        args = Mock(spec=['path'])
134
        args.path = 'path/to/directory'
135
        error = Mock()
136
        # Act
137
        ext = utilities.get_ext(args, error, '.out', '.file', whole_tree=True)
138
        # Assert
139
        self.assertEqual(0, error.call_count)
140
        self.assertEqual('.file', ext)
141
142
    def test_get_ext_file_document_no_extension(self):
143
        """Verify an extension is required on single file paths."""
144
        args = Mock(spec=['path'])
145
        args.path = 'path/to/file'
146
        error = Mock()
147
        # Act
148
        utilities.get_ext(args, error, '.out', '.file')
149
        # Assert
150
        self.assertNotEqual(0, error.call_count)
151
152
153
class TestAsk(unittest.TestCase):
154
155
    """Unit tests for the `ask` function."""
156
157
    def test_ask_yes(self):
158
        """Verify 'yes' maps to True."""
159
        with patch('builtins.input', Mock(return_value='yes')):
160
            response = utilities.ask("?")
161
        self.assertTrue(response)
162
163
    def test_ask_no(self):
164
        """Verify 'no' maps to False."""
165
        with patch('builtins.input', Mock(return_value='no')):
166
            response = utilities.ask("?")
167
        self.assertFalse(response)
168
169
    def test_ask_interrupt(self):
170
        """Verify a prompt can be interrupted."""
171
        with patch('builtins.input', Mock(side_effect=KeyboardInterrupt)):
172
            self.assertRaises(KeyboardInterrupt, utilities.ask, "?")
173
174
    def test_ask_bad(self):
175
        """Verify a bad response re-prompts."""
176
        with patch('builtins.input', Mock(side_effect=['maybe', 'yes'])):
177
            response = utilities.ask("?")
178
        self.assertTrue(response)
179
180
181
class TestShow(unittest.TestCase):
182
183
    """Unit tests for the `show` function."""  # pylint: disable=R0201
184
185
    @patch('builtins.print')
186
    def test_show(self, mock_print):
187
        """Verify prints are enabled by default."""
188
        msg = "Hello, world!"
189
        utilities.show(msg)
190
        mock_print.assert_called_once_with(msg, flush=False)
191
192
    @patch('builtins.print')
193
    @patch('doorstop.common.verbosity', common.PRINT_VERBOSITY - 1)
194
    def test_show_hidden(self, mock_print):
195
        """Verify prints are hidden when verbosity is quiet."""
196
        utilities.show("This won't be printed.")
197
        mock_print.assert_never_called()
198
199
200
class TestPositiveInt(unittest.TestCase):
201
202
    """ Unit tests for the `positive_int` function."""
203
204
    def test_positive_int(self):
205
        """Verify a positive integer can be parsed."""
206
        self.assertEqual(utilities.positive_int('1'), 1)
207
        self.assertEqual(utilities.positive_int(1), 1)
208
209
    def test_non_positive_int(self):
210
        """Verify a non-positive integer is rejected."""
211
        self.assertRaises(ArgumentTypeError, utilities.positive_int, '-1')
212
        self.assertRaises(ArgumentTypeError, utilities.positive_int, -1)
213
        self.assertRaises(ArgumentTypeError, utilities.positive_int, 0)
214
215
    def test_non_int(self):
216
        """Verify a non-integer is rejected."""
217
        self.assertRaises(ArgumentTypeError, utilities.positive_int, 'abc')
218